std :: map thread-safety

dee*_*zen 23 c++ multithreading stdmap map

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

std::map< std::string, Object >   _objects;
Run Code Online (Sandbox Code Playgroud)

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

Yak*_*ont 23

C++ 11标准保证const对容器的方法访问对于不同的线程是安全的(即两种使用const方法).

另外,[container.requirements.dataraces]说明

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

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

现在,如果一个线程使另一个线程使用的迭代器无效,显然这是一个数据争用(并导致未定义的行为).如果一个线程不const访问容器,而另一个线程const访问,则表示数据争用(以及未定义的行为).(注:一些功能被"视为const"对多线程的,其中的目的begin,end以及其他功能(和是非的方法)const,只是因为它们返回非const迭代器. []包含在这组假的const线程安全的原因,除了mapunordered_set等 - 23.2.2.1).

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

对于标准参考,17.6.5.9.5似乎保证标准库中的函数不会失控并且不必要地读/写元素.

所以简短的回答:你是安全的,只要其他线程没有直接搞乱那个特定的条目map.


Jon*_*ely 9

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

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

尽管如此(17.6.5.9),当同一序列中不同元素中包含的对象的内容vector<bool>同时被修改时,需要实现以避免数据争用.

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

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