此场景下std::unordered_map是否具备线程安全性?
共享std::unordered_map的线程安全性问题
假设有两个线程共享同一个std::unordered_map<int, std::vector<int>>实例:
- 线程1持续调用
insert_data函数,负责向容器中添加数据 - 线程2反复调用
iteration函数,负责遍历并输出容器内容
insert_data函数代码
void insert_data(int key, int value, std::unordered_map<int, std::vector<int>>& my_map) { if (my_map.find(key) == my_map.end()) { my_map[key] = std::vector<int>(); } my_map[key].push_back(value); }
iteration函数代码
void iteration(std::unordered_map<int, std::vector<int>>& my_map) { for (auto& [key, value] : my_map) { std::cout<<"key : "<<key<<" value : "<<value<<std::endl; } }
结论:这种场景完全不线程安全,会触发未定义行为,原因如下:
违反C++标准容器并发规则
根据C++标准,当有线程对标准容器执行写入操作(包括插入元素、修改容器内元素)时,其他线程不能同时执行读取或遍历操作,否则会产生数据竞争,属于未定义行为。此处insert_data中的my_map[key](可能触发插入)和push_back(修改vector)都是写入操作,iteration的遍历属于读取操作,无同步的并发执行必然触发数据竞争。竞态条件引发逻辑错误
insert_data里的find和operator[]组合不是原子操作:线程A执行find发现键不存在后,线程B可能也执行find得到相同结果,随后两个线程都会执行my_map[key] = std::vector<int>(),这会导致重复初始化,甚至破坏unordered_map的内部哈希表结构。迭代器失效导致崩溃或乱码
unordered_map插入元素时可能触发rehash(负载因子超阈值时),此时容器内所有迭代器都会失效。如果iteration线程正在遍历,使用失效迭代器会直接导致程序崩溃、输出乱码等不可预测结果。另外,即使不触发rehash,对vector的push_back可能引发内存重分配,遍历线程访问该vector时也可能读到无效数据。
内容的提问来源于stack exchange,提问作者demonic3540
相关产品推荐
相关产品推荐

