在多线程环境中使用没有锁定的std映射是否安全? 保证两个线程永远不会在地图中操纵相同的条目。
已经存在一个问题,但我对多个线程访问地图中不同条目的情况特别感兴趣。特别是无序的地图。
答案 0 :(得分:8)
只要没有线程正在修改地图,它就是安全的。如果线程正在修改地图的不同元素也是安全的(前提是元素本身不会因为修改某些全局状态而导致竞争条件):
在 17.6.5.9数据竞争规避中,标准库保证对容器的并发const
访问是安全的(至少在容器的范围内)。如果元素允许突变,则const
访问可以在元素级别进行数据竞争。)
在 23.2.2容器数据竞赛中进一步保证:如果修改/读取是对容器元素,则非const并发访问是安全的> 1
只要有一个线程对容器或容器中的同一元素进行修改而其他线程读取或写入,您就会对竞争条件和未定义的行为持开放态度。
1 std::vector<bool>
答案 1 :(得分:2)
根据C++11 23.2.2 Container data races /2
:
尽管如此(17.6.5.9),当同时修改
vector<bool>
以外的同一序列中不同元素中的包含对象的内容时,需要实现以避免数据争用。
部分17.6.5.9
只是说明了应用于实现的限制,因此 it 不会导致数据争用。
该文本基本上意味着您必须处理自己的竞争条件,容器本身不会这样做。
答案 2 :(得分:2)
仅访问地图的const成员的线程不会相互竞争。这在库规范的开头的库类型要求中指定。
访问非const成员的线程可以与访问const或非const成员的线程竞争。
换句话说,它们几乎与其他任何对象一样,并且没有额外的线程安全保证。标准库目前不包含特殊的线程安全容器。
答案 3 :(得分:1)
在多线程环境中使用没有锁定的std映射是否安全?保证两个线程永远不会在地图中操纵相同的条目。
您可以自由地操作映射中的不同现有条目(仅限值,因为映射API禁止键的变异),但应该使用某些同步工具在任何其他线程尝试访问或改变它们之前写出更改。
对于unordered_map
,insert
(即使是[]
),emplace
,erase
,reserve
,rehash
(明确的或者自动),operator=
,clear
不能安全地完成,而其他线程所做的不仅仅是访问/变异已经找到地址的元素,因为上述函数可以修改跟踪元素的基础哈希表数据结构和每桶链接列表。 &#34;超过&#34;包括find
,[]
等内容,即使在现有元素at
,equal_range
,甚至empty
,size
和load_factor
上也是如此以及所有bucket
次操作。