std::shared_mutex 是不是偏爱作者而不是读者?

Posted

技术标签:

【中文标题】std::shared_mutex 是不是偏爱作者而不是读者?【英文标题】:Does std::shared_mutex favor writers over readers?std::shared_mutex 是否偏爱作者而不是读者? 【发布时间】:2019-08-29 09:18:20 【问题描述】:

从 C++17(C++14) 开始,我们有了 std::shared_(timed_)mutex 类。 很长一段时间以来,Qt 都有一个类似的类 QReadWriteLock。 QReadWriteLock 的documentation 说:

为了确保作者不会被读者永远屏蔽,读者 如果有阻塞,尝试获取锁将不会成功 writer 等待访问,即使当前只访问了锁 由其他读者。此外,如果锁被写入者访问并且 另一位作家进来,该作家将优先于任何 可能也在等待的读者。

由于这当然是一个合理的财产,我想知道是否 std::shared_mutex 和 std::shared_timed_mutex 的行为方式相似吗?

【问题讨论】:

呵呵,是什么让你觉得我想暗示问题的意思不明确?无论如何我同意我的回答是无意义的并删除它 cpp 参考没有说明任何内容——只要它在这方面与标准没有区别(没有查过),显然实现是未指定的。所以每个编译器都可能按照它想要的方式处理它。我个人会按照先到先得的方式实施,这对我来说是最自然的...... 在shared_mutex 和shared_timed_mutex 的文档中都没有提到读/写优先于锁定。检查这一点的唯一方法是实现的源代码。 @Tony 好吧,也可以编写一个小测试程序。但两者都只会显示 your 编译器的实现。其他人可能会有所不同... @Aconcagua 确实如此。 【参考方案1】:

官方 C++ 标准未指定 std::shared_mutex 策略。可以在原始 N2406 提案中找到解释 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#shared_mutex_imp) 在 shared_mutex 参考实现 部分:

次要动机是解释 shared_mutex 中缺少读写器优先级策略。这是由于一种归功于 Alexander Terekhov 的算法,它让操作系统决定哪个线程是下一个获得锁的线程,而无需关心是否正在寻找唯一锁或共享锁。这导致完全没有读者或作者饥饿。这很公平。

与 QReadWriteLock 实现相比(即 write-preferring):

为确保写入器不会被读取器永远阻塞,如果存在等待访问的阻塞写入器,尝试获取锁的读取器将不会成功,即使该锁当前只有其他读取器访问。

提案的shared_mutex 也是如此,以确保如果新读者继续出现,作者不会永远等待。

另外,如果一个写者访问了锁,而另一个写者进入,则该写者将优先于任何可能也在等待的读者。

提案的shared_mutex 并非如此,在这种情况下,读者和作者的优先级相同。

但不幸的是,最终的 C++ 标准文档不包含此参考实现。请注意,尽管 GCC 包含基于 N2406 参考实现的std::shared_mutex 实现,但在 Linux 上默认不使用它,它使用来自 POSIX 线程库的pthread_rwlock_t(由_GLIBCXX_USE_PTHREAD_RWLOCK_T 中的_GLIBCXX_USE_PTHREAD_RWLOCK_T 选项控制)。 pthread_rwlock_t 可以是读优先或写优先,具体取决于系统设置和应用的pthread 属性。详情见相关问题:How to prevent writer starvation in a read write lock in pthreads

【讨论】:

【参考方案2】:

标准没有规定。

POSIX 没有指定 pthread rwlocks 必须如何决定下一个锁请求是否成功,因此如果有这样的要求,就不可能按照标准 pthreads 实现 C++ std::shared_mutex

因为这当然是一个合理的属性

这当然是一个合理的属性,但它不是唯一合理的属性。

例如,GLIBC 有一个 pthreads 扩展,允许您从三种 rwlock 策略中进行选择:递归优先读取器、递归优先写入器和非递归优先写入器。大概 recursive prefer writer 并不是所有程序的正确选择。


为了确保作者不会被读者永远阻止......

顺便说一句,这并不能确保写入器不会被其他写入器永远阻止。

直观-完美-公平的解决方案是 shared-reader-preferred-exclusive-FIFO-ordered-writer,但这对于许多目的来说是不必要的重量级。

Qt 版本可能非常适合 Qt 的用例,但它只是轻型/高效 -- 重型/公平频谱上的一点。

【讨论】:

谢谢。我希望我可以将两个答案标记为答案。

以上是关于std::shared_mutex 是不是偏爱作者而不是读者?的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 std::shared_mutex 上使用 std::shared_lock 更改数据吗?

C++关于锁的总结

boost的线程库和c++11的线程序有何不同

锁前后检查资源

为啥 Swift 2 偏爱强制解包而不是可选项?

为什么很多硅谷工程师偏爱 OS X,而不是 Linux 或 Windows