所以我们创建了一张地图。我们希望得到some_type blah = map_variable[some_not_inserted_yet_value]
这会调用添加新项目来映射,如果没有预先创建。所以我想知道读取是否真的是std::map
的线程安全,或者它只能安全地线程try{ ...find(..)->second...
?
答案 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
进行比较,以查看是否找到了该项目。 (另请注意,find
有const
个版本,而operator[]
没有。{/ p>
就像其他人所说的那样,C ++ 11之前的C ++版本没有线程或线程安全的概念。但是,在没有同步的情况下使用find
可以感觉很安全,因为它不会更改容器,因此它只执行读取操作(除非您有一个奇怪的实现,因此请务必检查文档)。与大多数容器一样,从不同的线程读取它不会造成任何伤害,但写入它可能会。