使用std :: unordered_map进行数据竞争,尽管使用互斥锁进行锁定插入

Kul*_*007 6 c++ concurrency containers stl unordered-map

我有一个C++ 11程序,它执行一些计算并使用a std::unordered_map来缓存那些计算的结果.该程序使用多个线程,并使用共享unordered_map来存储和共享计算结果.

基于我对unordered_mapSTL容器规范的读取以及unordered_map线程安全性,似乎unordered_map多个线程共享的一个线程可以一次处理一个线程,但一次只能处理许多读者.

因此,我使用a std::mutex将我的insert()调用包装到地图中,因此一次最多只插入一个线程.

但是,我的find()调用没有互斥,因为从我的阅读来看,似乎许多线程应该能够立即读取.但是,我偶尔会得到数据竞赛(由TSAN检测到),在SEGV中表现出来.这些数据清楚地赛点的insert(),并find()调用我上面提到的.

当我find()用互斥锁包装调用时,问题就消失了.但是,我不想序列化并发读取,因为我试图尽可能快地使这个程序.(仅供参考:我正在使用gcc 5.4.)

为什么会这样?我对并发保证的理解std::unordered_map不正确吗?

Gal*_*lik 6

您仍然需要一个mutex供读者使用的工具,以将作者拒之门外,但您需要一个共享的工具C++14具有一个std :: shared_timed_mutex,您可以将其与范围锁std :: unique_lockstd :: 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';
}
Run Code Online (Sandbox Code Playgroud)