C++ c+的RW锁+;11线

C++ c+的RW锁+;11线,c++,multithreading,c++11,C++,Multithreading,C++11,我想使用新的标准线程而不是boost:threads,但我注意到旧的shared_互斥体不可用。替换此功能并给我一个多读卡器、单写器锁的好建议是什么?std::shared_mutex将是C++14标准库的一部分。它并没有到达C++11,只是因为并没有时间制定一个提案并进行彻底的讨论 不过,您仍然可以使用boost::shared_mutex。在Windows下,如果您使用的是Windows Vista或更高版本,您可以使用,它针对速度和内存消耗进行了优化。您应该查看堆栈溢出问题“”,特别是以下

我想使用新的标准线程而不是boost:threads,但我注意到旧的shared_互斥体不可用。替换此功能并给我一个多读卡器、单写器锁的好建议是什么?

std::shared_mutex
将是C++14标准库的一部分。它并没有到达C++11,只是因为并没有时间制定一个提案并进行彻底的讨论


不过,您仍然可以使用
boost::shared_mutex
。在Windows下,如果您使用的是Windows Vista或更高版本,您可以使用,它针对速度和内存消耗进行了优化。

您应该查看堆栈溢出问题“”,特别是以下链接电子邮件对话:(这解释了C++11委员会拒绝批准共享互斥锁的原因)。还有乔·达菲的博客上的以下实验:

每次考虑读写器锁定时,问自己以下6个问题。如果您对其中任何一个都能回答“否”,那么读写器锁将使您的程序变得更糟,而不是更好

  • 我的共享对象是常量吗?在我的生活中,不正确使用
    共享互斥体的情况比正确使用的情况要多。要正确使用
    shared_mutex
    ,必须在读卡器关键部分内声明共享对象
    const
    ,而无需任何编译器投诉。“消费者”并不等同于“完全不改变数据结构的人”
  • 我的关键部分真的很长吗?锁定共享互斥比锁定普通互斥昂贵得多。您必须在关键部分进行大量工作,以弥补锁获取/释放增加的开销
  • 我的关键部分应该那么长吗?你应该问问自己,你是否真的需要在一个关键的部分做所有的工作。通常,围绕着对共享对象的
    const
    调用,有一系列准备工作和/或处理返回对象的工作。从第一次使用共享对象到最后一次使用共享对象,很多不在数据依赖路径上的额外工作可以转移到关键部分之外
  • 锁争用真的是我的性能问题吗?即使您的关键部分很长,您也应该绝对确定锁争用确实是您的性能问题。如果您没有遇到严重的锁争用,那么切换到读写器锁并不能为您带来任何好处
  • 我可以通过切换到更细粒度的锁定方案来减少锁争用吗?您是否使用单个锁来保护多个对象?你能给每个对象一个锁吗
  • 读者与作者的比例是否明显大于1:1?即使您的关键部分很长,并且锁争用是一个严重的问题,读写器的比率也需要非常高,才能从读写器锁中获得任何好处。数量取决于硬件上原子指令的成本和特定实现的质量。(乔·达菲发现,在他的机器上,他需要大约20:1的读写比,才能使读写锁获胜。)

  • 尽管乔·达菲的那篇文章需要谨慎阅读。假设由于一种特定类型的rw锁(在.NET中)的一个实现以某种方式运行,因此通常对rw锁没有多大影响。rw锁不必比临界截面对象慢,也不必使用CAS操作。有这么多的变化,例如,它不必是公平的(或者,它可能不得不)。根据具体情况,rw锁可能比互斥锁效率更高(2-3个数量级)。对r/w比率的看法也很有趣。。。。。。1比20的比例也很有趣。这并不是什么特别的事情。在一项任务中使用错误的工具肯定最多只能得到平庸的结果。这就像抱怨使用
    std::list
    在随机访问时性能不佳,或者
    std::vector
    在前面插入数百万个元素时性能不佳。如果您的读操作数不超过写操作数,那么当然rw锁是不可能赢的(也可能是输的)。但这是使用了错误的工具。达菲的例子是每0.25ms(=250000ns)就有一个请求,这也是一个很好的例子。这是一个“完全零拥堵”的案例。在这种情况下,甚至想到CAS操作的过度成本(通常小于25纳秒)也让我觉得很有趣。一个现代的CPU不会因为每秒执行4000个原子操作而受到挑战。@WanderingLogic你能详细说明第一点吗?那么什么是消费者呢?为什么需要编译时常量严格?至于编译时常量严格。我并不是说你实际上必须声明你的对象常量。相反,您只需要确保线程在修改共享对象时始终具有writer锁。您需要完全了解哪些方法会改变共享对象。(也就是说,您必须了解在writer锁之外的共享对象上调用的每个非const方法的实现。)linux上的pthreads也有
    pthread\u rwlock
    不是在C++14中,而是在C++17中。我认为更好的副本是。当前副本要求手动实现,而另一个副本要求标准化的读/写锁。