读取std :: map / std :: unordered_map的安全性

时间:2016-08-25 21:49:58

标签: c++11 concurrency thread-safety stdmap

我有一个std :: map(或者std :: unordered_map,因为我认为它们的行为类似)我读写的内容。我也有一个相关的互斥锁。

我将同时阅读和写入(通过插入或删除元素)到地图。我听说STL容器是安全的。如果是这样,只使用互斥锁进行写操作是安全的吗?

我问,因为我需要在某一点迭代地图的值,并且我只想在元素需要修改时才使用我的互斥锁。

2 个答案:

答案 0 :(得分:1)

  

只使用互斥锁进行写操作是安全的吗?

您需要确保在写入地图时不要尝试从地图中读取数据。所以你不需要在只读取时锁定互斥锁,但如果任何线程可能正在编写,那么所有线程(甚至读者)都需要使用互斥锁。

答案 1 :(得分:0)

一般来说,没有。读者和作者都必须获得互斥锁。

否则,当存在并发读取和写入时,您将面临数据争用的风险,从而导致未定义的行为。在实践中,可能导致崩溃,或者读者可能会获得您从未放入地图的损坏数据。即使如果它似乎有效,它也会混淆有用的工具,比如种族探测器(例如,thread sanitizerHelgrind)。它还使您的代码可能不可移植。

只有当您能够证明地图上没有更多的编写者,并且所有其他线程都可以看到更改时,情况就会发生变化,因为现在所有访问都是读者。此时,不会有任何数据争用,并且可以安全地从地图中读取而不进行任何同步。

如果仍有更新的可能性,您可以使用并行数据结构来避免锁定。 C ++ 11(和C ++ 17)没有提供,但有非标准的实现可用。

因此,如果您确实需要性能,可以查看这些并发哈希映射实现(否则只需将std::unordered_map与互斥锁结合使用):

    英特尔线程构建模块(TBB)中的
  • Concurrent data structures
  • Junction(似乎是最快的,但要求线程在不使用map时定期调用清理操作。这样做是为了回收内存而不必使用垃圾收集器,如介绍blog post中的“安全记忆回收”。)
相关问题