是`std :: map< ..>一个; blah = a [abcd];`如果在此调用之前未创建abcd,则线程安全吗?

时间:2011-08-26 02:57:38

标签: c++ multithreading stl map std

所以我们创建了一张地图。我们希望得到some_type blah = map_variable[some_not_inserted_yet_value]这会调用添加新项目来映射,如果没有预先创建。所以我想知道读取是否真的是std::map的线程安全,或者它只能安全​​地线程try{ ...find(..)->second...

4 个答案:

答案 0 :(得分:3)

调用find(...)->second是线程安全的想法非常依赖于您对线程安全的看法。如果你只是意味着它不会崩溃,那么只要没有人在你阅读它的同时改变字典,我想你没事。

实际上,无论您的最低线程安全要求是什么,调用operator[]方法本质上都是线程安全,因为它可以改变集合。

如果方法没有const重载,则意味着它可以改变对象,因此除非文档指出方法是线程安全的,否则该方法不太可能。

然后,const方法也可能不是线程安全的,因为您的对象可能依赖于非const全局状态或具有mutable字段,因此您将如果你使用非同步类,就要非常非常小心。

答案 1 :(得分:2)

如果您100%确定地图包含密钥,那么如果所有其他线程也只是在地图上调用只读方法,那么技术上线程安全。但请注意,const没有map<k,v>::operator[](const k&)版本。

以线程安全的方式访问地图的正确方法确实是:

map<k,v>::const_iterator match = mymap.find(key);
if ( match != mymap.end() ) {
    // found item.
}

如前所述,这仅适用于所有并发访问权限为只读的情况。可以保证的一种方法是使用readers-writers lock

请注意,在C ++ 03中,标准中没有提及线程,所以即使这样也不保证是线程安全的。请务必查看您的实施文档。

答案 2 :(得分:1)

标准库容器没有线程安全的概念。您必须自己同步对容器的并发读/写访问权。

try与多线程无关。它用于异常处理。

如果找不到密钥,

find不会抛出异常。如果找不到密钥,find将返回地图的end()迭代器。

答案 3 :(得分:0)

你是对的,operator[]不是“线程安全的”,因为它可以改变容器。您应该使用find方法并将结果与​​std::map::end进行比较,以查看是否找到了该项目。 (另请注意,findconst个版本,而operator[]没有。{/ p>

就像其他人所说的那样,C ++ 11之前的C ++版本没有线程或线程安全的概念。但是,在没有同步的情况下使用find可以感觉很安全,因为它不会更改容器,因此它只执行读取操作(除非您有一个奇怪的实现,因此请务必检查文档)。与大多数容器一样,从不同的线程读取它不会造成任何伤害,但写入它可能会。