5

我有一个std::unordered_map受到来自多个线程的非常重的读取工作负载的影响。我可以使用 astd::mutex进行同步,但由于并发读取应该没问题,我想使用 aboost::shared_mutex代替。为了测试性能改进,我首先用一堆值预先填充了一个映射,然后让一堆线程运行读取测试

for (int i = 0; i < iters; ++i) map.count(random_uint(0, key_max));

我为我受保护的粗实现和受.countstd::lock_guard<std::mutex>boost::shared_lock<boost::shared_mutex>

在我的带有 GCC 6.1.1 的 Arch Linux x86_64 系统上,boost::shared_lock版本总是较慢!在我朋友的装有 MSVC 2013 的 Windows 10 系统上,boost::shared_lock总是更快! 完整的、可编译的代码在 github 上:https ://github.com/silverhammermba/sanity

编辑

这似乎是一个特定于平台的问题。看上面。如果其他人可以构建和运行此代码并报告他们是否看到正输出(shared_lock更快)或负输出(当然互斥锁更快)以及您使用的平台,我将非常感激。

4

2 回答 2

10

事实证明,这在 Linux 上boost::shared_mutex“次优的” 。

'pthread' 的 boost::shared_mutex 的当前(从 boost 1.59 开始)实现非常不理想,因为它使用重量级互斥锁来保护内部互斥锁状态...... [当访问并发性很高时] 共享互斥锁实际上是排他的。

万岁的提升和我生命中的许多小时被它偷走了。

于 2016-05-18T17:27:21.380 回答
-3

几点注意事项:

  1. 如果您的数据结构存在高竞争,强烈建议使用具有无锁实现的相同数据结构

  2. Reader-Writer 锁通常在读取很常见时会带来性能提升,但写入很少。从哲学上讲,如果锁必须确定其他线程是否以读模式或写模式捕获了锁,它比简单地等待锁被释放要慢。因此,如果读取很常见而写入很少,则其他线程不会被阻塞。如果写入很常见,不仅线程被阻塞,而且它们必须执行额外的逻辑来确定如何锁定什么。

因此,总而言之,您的示例以不好的方式使用了锁。此外,如果性能要求您,请使用无锁编程。

于 2016-05-18T15:13:07.707 回答