c++ - 插入时并发遍历 map ,以何种方式不安全

标签 c++ c++11 optimization visual-studio-2015 concurrency

注意:我知道这是不安全的,并且是标准未定义的,正在查看它是否由我的编译器定义,或者在实践中是否安全。

我在一个线程中遍历映射范围,同时可能在另一个线程中插入

// thread 1:
for(auto it = map.begin(); it != map.end(); ++it){
    // it's okay if "it" is out of order, repeats an element, or skips an element
    // it's bad  if "it" can skip map.end() or turn to mush (invalid iterator)
}

// thread 2:
map[Key(...)] = Type(...); // insertions are extremely rare but inevitable

这是不安全的,但是嗯……有多不安全?此映射用作缓解线程争用的优化提示,因此它本身不会导致该争用。如果可能的结果只是插入的元素可能被遗漏,或者它会乱序读取元素或两次,这是可以接受的,不会破坏任何东西。

这样做会把迭代器变成汤还是导致 map.end() 被遗漏?这是仅有的两个可能毁了我一生的结果。

最佳答案

是的,这些结果绝对有可能发生,甚至更糟

当您插入 map 时,会发生各种内部操作。它不仅仅是一个 []=:下面有一个完整的算法,可能包括重新平衡操作! (有关更多信息,请参阅有关树结构管理的旧大学笔记。)

对于在这种算法过程中“观察” map 会产生什么结果,没有任何保证,并且标准非常清楚地表明您的程序将具有未定义的行为。这是一个双重问题:不仅您可能会遇到映射的实际问题,而且您的编译器知道没有明确定义的程序会遇到这种情况,并且可以根据您没有这样做的假设进行优化't。现在一切都乱套了,potentially in code not even related to your map accesses .

在一个线程中修改 map 并在另一个线程中读取 map ,如果不进行同步,这就是自杀,简单明了。不要试图比编译器/实现更聪明:只需编写代码即可。

关于c++ - 插入时并发遍历 map ,以何种方式不安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54065064/

相关文章:

algorithm - 贪心算法实现,Haskell

c++ - wxTreeListCtrl 的链接器错误

c++ - 编译器跳过 C++ 中的可变参数模板/函数

c++ - 有没有一种很好的方法来实现具有默认失败情况的条件类型?

.net - 排序列表中的部分键匹配 <string>

optimization - 如何优化 MATLAB 循环?

c++ - std::queue 位置的包装器

c++ - 如何在 Linux 上守护一个 c/c++ 程序

c++ - 无法抑制 GCC -Wextra 警告

exception - 是否有需要启用异常的 c++11 标准库接口(interface)列表?