std :: map thread-safety

时间:2013-02-25 12:38:34

标签: c++ multithreading map stdmap

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

std::map< std::string, Object >   _objects;
可以从许多线程更改

映射,并且此访问是同步的,但是只能从1个实例和线程访问值(Object&amp;)。是对象&amp;写的操作。如果另一个线程将项添加到地图是安全的吗?它会重新分配吗?

2 个答案:

答案 0 :(得分:18)

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

此外,[container.requirements.dataraces]陈述

  

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

之外

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

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

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

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

所以简短的回答:你是安全的,只要另一个线程没有直接弄乱map中的特定条目。

答案 1 :(得分:7)

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

该标准保证不同的线程可以修改不同的元素,在[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最后一块拼图)