我有一个 C++11 程序,它执行一些计算并使用 std::unordered_map
来缓存这些计算的结果。该程序使用多个线程,它们使用共享的 unordered_map
来存储和共享计算结果。
基于我对 unordered_map
和 STL 容器规范的阅读,以及 unordered_map thread safety ,似乎一个unordered_map
,被多个线程共享,一次可以处理一个线程写入,但是一次可以处理多个读取器。
因此,我使用 std::mutex
来包装我对 map 的 insert()
调用,这样最多只有一个线程插入时间。
但是,我的 find()
调用没有互斥锁,因为从我的阅读来看,似乎许多线程应该能够同时读取。但是,我偶尔会遇到数据竞争(由 TSAN 检测到),这会在 SEGV 中表现出来。数据争用显然指向我上面提到的 insert()
和 find()
调用。
当我将 find()
调用包装在互斥锁中时,问题就消失了。但是,我不想序列化并发读取,因为我试图让这个程序尽可能快。 (仅供引用:我正在使用 gcc 5.4 运行。)
为什么会这样?我对 std::unordered_map
的并发保证的理解不正确吗?
最佳答案
您仍然需要一个互斥体
让您的读者将作者拒之门外,但您需要一个共享。 C++14
有一个 std::shared_timed_mutex可以与作用域锁一起使用 std::unique_lock和 std::shared_lock像这样:
using mutex_type = std::shared_timed_mutex;
using read_only_lock = std::shared_lock<mutex_type>;
using updatable_lock = std::unique_lock<mutex_type>;
mutex_type mtx;
std::unordered_map<int, std::string> m;
// code to update map
{
updatable_lock lock(mtx);
m[1] = "one";
}
// code to read from map
{
read_only_lock lock(mtx);
std::cout << m[1] << '\n';
}
关于c++ - 与 std::unordered_map 的数据竞争,尽管使用互斥锁定插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38061067/