Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 插入时并发迭代映射,以何种方式不安全_C++_C++11_Optimization_Visual Studio 2015_Concurrency - Fatal编程技术网

C++ 插入时并发迭代映射,以何种方式不安全

C++ 插入时并发迭代映射,以何种方式不安全,c++,c++11,optimization,visual-studio-2015,concurrency,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

注意:我知道这是不安全的,并且标准没有定义,我想看看它是由我的编译器定义的,还是在实践中是安全的

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

// 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()
?这是唯一两个可能毁掉我生活的结果。

我在这里只是半开玩笑,但假设基础集合是通过预先分配一个固定大小来实现的,那么当需要增长时,它可能会多分配50%,以避免重复、小规模的重新分配。然后,旧集合项将被移动到新分配的内存中,旧集合将被解除分配


如果您在插入时迭代这样一个集合,“下一个”迭代器可能会最终持有一个指向释放位置的指针。

我在这里只是随便说说,但假设基础集合是通过预先分配一个固定大小来实现的,那么当需要增长时,它可能会多分配一个指针,例如50%,以避免重复,小规模再分配。然后,旧集合项将被移动到新分配的内存中,旧集合将被解除分配


如果在插入时对这样的集合进行迭代,“下一个”迭代器可能最终持有指向已释放位置的指针。

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

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

对于在这种算法过程中“观察”地图会产生什么结果,没有任何保证,标准非常清楚地表明,您的程序将具有未定义的行为。这是一个双重问题:您不仅会遇到映射的实际问题,而且您的编译器知道没有定义良好的程序会遇到这种情况,并且可以基于您没有遇到的假设进行优化。现在所有的地狱都散去了


在一个线程中修改地图,在另一个线程中读取地图,而不进行同步,这是自杀式的,简单明了。不要试图智胜编译器/实现:只需编写契约代码。

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

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

对于在这种算法过程中“观察”地图会产生什么结果,没有任何保证,标准非常清楚地表明,您的程序将具有未定义的行为。这是一个双重问题:您不仅会遇到映射的实际问题,而且您的编译器知道没有定义良好的程序会遇到这种情况,并且可以基于您没有遇到的假设进行优化。现在所有的地狱都散去了


在一个线程中修改地图,在另一个线程中读取地图,而不进行同步,这是自杀式的,简单明了。不要试图智胜编译器/实现:只需编写契约代码。

这是非常不安全的-映射可以重新分配(即,读取时可能会出现seg错误)。您应该使用互斥锁来保护插入和访问。@GeorgiGerganov-
std::map
迭代器在插入后保持有效,映射的内容在内存中应该是不可移动的,但插入不是原子的,因此增加迭代器可能会在构造中指向(无效)
Node
。@Jarod42-啊,我没想到,单凭这一点就可以打破局面。感谢insightOk,看来我的评论可能不完全正确-在地图中插入时不会发生重新分配(感谢下面的@corolla comment)。这非常不安全-地图可以重新分配(即,您可以在阅读时获得seg故障)。您应该使用互斥锁来保护插入和访问。@GeorgiGerganov-
std::map
迭代器在插入后保持有效,映射的内容在内存中应该是不可移动的,但插入不是原子的,因此增加迭代器可能会在构造中指向(无效)
Node
。@Jarod42-啊,我没想到,单凭这一点就可以打破局面。谢谢你的见解,看来我的评论可能不完全正确-在地图中插入时不会发生重新分配(感谢下面的@corolla comment)。基于节点的集合(如地图和列表)与基于块的集合(如向量)具有不同的分配语义。基于节点的集合(如地图和列表)与基于块的集合(如向量)具有不同的分配语义。