我有一个
std::map<std::string, std::tuple<int, int, std::atomic<int>>> mp
。该映射可以并行读写,因此我使用读写锁来保持线程安全。
我想知道我是否可以在读锁定区域写入
std::get<2>(mp["someKey"])
。
void read() {
// read lock area
std::shared_lock<std::shared_mutex> read_lock{mtx};
// "someKey" exists already
std::get<2>(mp["someKey"]).store(2);
}
我尝试做一些测试,似乎它有效,但我不知道它是否不正确,并有一天给我一个核心转储。
首先,请注意
mp["someKey"]
修改了地图并且不是线程安全的。如果还不存在键,operator[]
将创建一个新的值初始化键/值对。相反,您应该使用 mp.at("someKey")
或 mp.find("someKey")
:
std::get<2>(mp.at("someKey")).store(2); // OK
if (auto it = mp.find("someKey"); it != mp.end()) { // OK
std::get<2>(*it).store(2);
}
.store(2);
是线程安全的,因为同时从多个线程写入 std::atomic
是安全的。
不需要 std::shared_lock
来确保这一点。但是,std::shared_lock
确保周围的 std::pair
不会被另一个线程破坏,因此必须保留它。