【发布时间】:2016-10-29 21:17:30
【问题描述】:
我有一个 C++11 程序,它执行一些计算并使用 std::unordered_map 来缓存这些计算的结果。该程序使用多个线程,它们使用共享的unordered_map 来存储和共享计算结果。
根据我对unordered_map 和STL 容器规范以及unordered_map thread safety 的阅读,似乎由多个线程共享的unordered_map 一次可以处理一个线程写入,但是很多读者同时时间。
因此,我使用std::mutex 将我的insert() 调用包装到映射中,这样一次最多只能插入一个线程。
但是,我的 find() 调用没有互斥锁,因为根据我的阅读,似乎许多线程应该能够同时读取。但是,我偶尔会遇到数据竞争(由 TSAN 检测到),在 SEGV 中表现出来。数据竞争清楚地指向了我上面提到的insert() 和find() 调用。
当我将 find() 调用包装在互斥体中时,问题就消失了。但是,我不想序列化并发读取,因为我试图让这个程序尽可能快。 (仅供参考:我正在使用 gcc 5.4 运行。)
为什么会这样?我对std::unordered_map的并发保证的理解不正确吗?
【问题讨论】:
-
听起来你需要一个
shared_mutex,因为你有一个作家,所有的读写调用都需要同步。 -
链接线程中的答案说:“A.多个线程同时读取, 或 B.一个线程同时写作”。注意或。
-
您误解了规范;它允许多个阅读器,但无论单个作者如何,都不允许多个阅读器。您需要像 NathanOliver 的评论中提到的 shared_mutex 一样的 Multiple Reader/Single Writer 锁
-
谢谢大家。这一切都说得通。回复:shared_mutex,这听起来确实是正确的解决方案。但是,我尝试了它,但我遇到了麻烦。我现在正在尝试使用stackoverflow.com/questions/19915152/… 描述的方法,并使用 -std=c++14 进行编译。然而,虽然它能够找到
标头(同样,我正在使用 gcc 5.4 运行),但我得到了 error: ‘shared_mutex’ in namespace ‘std’ does not name a type。似乎 shared_mutex 可能直到 c++17 才可用?有关如何使其正常工作的任何快速指示? -
标准线程安全规则适用于
std::unordered_map,就像它们适用于大多数类一样。标准线程安全意味着一个线程不能访问一个对象,而另一个线程正在或可能正在修改它。
标签: c++ concurrency stl containers unordered-map