C++ std::map 线程安全

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15067160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:58:50  来源:igfitidea点击:

std::map thread-safety

c++multithreadingmapstdmap

提问by deeptowncitizen

Is reference to object in std::map is thread safe?

对 std::map 中的对象的引用是线程安全的吗?

std::map< std::string, Object >   _objects;

map can be changed from many threads and this access is synchronized, but reference to value (Object &) accessable just from 1 instance and thread. is write operations with Object & is safe if another thread will add items to map? will it reallocate?

可以从多个线程更改映射,并且此访问是同步的,但对值 (Object &) 的引用仅可从 1 个实例和线程访问。如果另一个线程将项目添加到映射,那么使用 Object & 的写操作是否安全?会重新分配吗?

回答by Yakk - Adam Nevraumont

The C++11 standard guarantees that constmethod access to containers is safe from different threads (ie, both use constmethods).

C++11 标准保证const从不同线程(即,都使用const方法)访问容器的方法是安全的。

In addition, [container.requirements.dataraces] states

此外,[container.requirements.dataraces] 声明

implementations are required to avoid data races when the contents of the contained object in different elements in the same sequence, excepting vector<bool>

当包含对象的内容在同一序列的不同元素中时,需要实现来避免数据竞争,除了 vector<bool>

In other words, except for vector<bool>modifying distinct contents is not a data race.

换句话说,除了vector<bool>修改不同的内容不是数据竞争。

Now, if one thread invalidates an iterator used by another thread, clearly this is a data race (and results in undefined behavior). If one thread does non-constaccess to a container, and another does constaccess, that is a data race (and undefined behavior). (Note: a number of functions are "considered const" for the purpose of multithreading, including begin, endand other functions (and methods) that are non-constsimply because they return non-constiterators. []is included in this set of pseudo-constfor thread safety reasons, except for mapand unordered_setetc -- 23.2.2.1).

现在,如果一个线程使另一个线程使用的迭代器无效,这显然是一种数据竞争(并导致未定义的行为)。如果一个线程不const访问容器,而另一个线程const访问,那就是数据竞争(和未定义的行为)。(注意:许多函数被“考虑const”用于多线程,包括beginend以及其他不const只是因为它们返回非const迭代器的函数(和方法)。出于线程安全的原因[]包含在这组伪函数中 const除了mapunordered_set等- 23.2.2.1)。

However, it appears that if you have a reference to an element within the container, and engage in operations that do not invalidate that reference in another thread, and never write to that element in another thread, you can safely read from that reference. Similarly, if other threads never even read from the element, then writing to that element shouldn't result in undefined behavior.

但是,如果您对容器中的某个元素有一个引用,并且参与的操作不会使另一个线程中的该引用无效,并且永远不会在另一个线程中写入该元素,那么您可以安全地从该引用中读取。类似地,如果其他线程甚至从未读取过该元素,则写入该元素不应导致未定义的行为。

For standards references, 17.6.5.9.5 seems to guarantee that functions from the standard library won't run away and read/write elements needlessly.

对于标准参考,17.6.5.9.5 似乎保证标准库中的函数不会跑掉,也不会不必要地读/写元素。

So the short answer: you are safe, so long as the other thread doesn't directly mess with that particular entry in the map.

所以简短的回答:你是安全的,只要另一个线程不直接与map.

回答by Jonathan Wakely

Elements in a map are stable, they do not get moved or invalidated unless the element is erased from the map. If only one thread is writing to a given object, and changes to the map itself are correctly synchronized, then I believeit will be safe. I'm sure it's safe in practice, and I think it's safe in theory too.

地图中的元素是稳定的,除非从地图中删除元素,否则它们不会被移动或失效。如果只有一个线程写入给定对象,并且对映射本身的更改正确同步,那么我相信它会是安全的。我确信它在实践中是安全的,我认为它在理论上也是安全的。

The standard guarantees that distinct elements can be modified by different threads, in [container.requirements.dataraces]

该标准保证不同的元素可以被不同的线程修改,在 [container.requirements.dataraces]

Notwithstanding (17.6.5.9), implementations are required to avoid data races when the contents of the contained object in different elements in the same sequence, excepting vector<bool>, are modified concurrently.

尽管 (17.6.5.9),当vector<bool>同时修改同一序列中不同元素中包含的对象的内容时,实现需要避免数据竞争,除了,。

This only allows you to modify the elements, not to insert new elements into the map while modifying elements. For some containers, such as std::vector, modifying the vector itself might also modify elements by reallocating and moving them, but [associative.reqmts]/9 ensures std::mapwon't invalidate existing elements.

这只允许您修改元素,而不是在修改元素时将新元素插入到地图中。对于某些容器,例如std::vector,修改向量本身也可能通过重新分配和移动元素来修改元素,但 [associative.reqmts]/9 确保std::map不会使现有元素无效。

Since no member function of std::mapis required to access the second member of its elements (i.e. the mapped_type) I think [res.on.data.races]/5 says no other thread will conflict with writes to that member when modifying the map. (Thanks to Yakk for that final piece of the puzzle)

由于不需要成员函数 ofstd::map来访问其元素的第二个成员(即mapped_type),我认为 [res.on.data.races]/5 表示在修改映射时没有其他线程会与对该成员的写入冲突。(感谢 Yakk 的最后一块拼图)