假设我有:
stl::map<std::string, Foo> myMap;
以下函数线程安全吗?
myMap["xyz"] ?
即我想拥有这个在许多线程之间共享的巨大只读映射;但我不知道即使搜索它是否是线程安全的。
一切都先写入一次。
然后,多个线程从中读取。
我试图避免锁定以使其尽可能快。(我知道,yaya 可能过早优化)
假设我有:
stl::map<std::string, Foo> myMap;
以下函数线程安全吗?
myMap["xyz"] ?
即我想拥有这个在许多线程之间共享的巨大只读映射;但我不知道即使搜索它是否是线程安全的。
一切都先写入一次。
然后,多个线程从中读取。
我试图避免锁定以使其尽可能快。(我知道,yaya 可能过早优化)
C++11 要求所有声明为的成员函数const
对于多个阅读器都是线程安全的。
调用myMap["xyz"]
不是线程安全的,因为std::map::operator[]
没有声明为const
. 调用myMap.at("xyz")
是线程安全的,因为std::map::at
声明为const
.
理论上没有 STL 容器是线程安全的。在实践中,如果容器没有被同时修改,读取是安全的。即该标准没有关于螺纹的规范。该标准的下一个版本将和 IIUC 将保证安全的只读行为。
如果您真的很担心,请使用带有二进制搜索的排序数组。
至少在微软的实现中,从容器中读取是线程安全的(参考)。
但是,std::map::operator[]
可以修改数据并且不声明const
。您应该改为使用std::map::find
,const
来获取 aconst_iterator
并取消引用它。
理论上,只读数据结构和函数不需要任何线程安全锁。它本质上是线程安全的。并发内存读取没有数据竞争。但是,您必须保证仅由单个线程进行安全初始化。
正如 Max S. 指出的那样,大多数在 map 中读取元素的实现myMap["xyz"]
都没有写操作。如果是这样,那么它是安全的。但是,再一次,您必须保证除了初始化阶段之外没有修改结构的线程。
STL 集合不是线程安全的,但是将线程安全添加到其中是相当简单的。
你最好的选择是围绕有问题的集合创建一个线程安全的包装器。