std :: map的线程安全性,用于只读操作

时间:2009-12-04 10:45:22

标签: c++ multithreading stl thread-safety stdmap

我有一个std :: map,用于将值(字段ID)映射到人类可读的字符串。当我的程序在任何其他线程启动之前启动时,此映射会初始化一次,之后永远不会再次修改。现在,我给每个线程自己的这个(相当大的)地图的副本,但这显然是低效的内存使用,它减慢了程序启动速度。所以我想给每个线程一个指向地图的指针,但这会引发一个线程安全问题。

如果我正在做的就是使用以下代码从地图上阅读:

std::string name;
//here N is the field id for which I want the human readable name
unsigned field_id = N; 
std::map<unsigned,std::string>::const_iterator map_it;

// fields_p is a const std::map<unsigned, std::string>* to the map concerned.
// multiple threads will share this.
map_it = fields_p->find(field_id);
if (map_it != fields_p->end())
{
    name = map_it->second;
}
else
{
    name = "";
}

从多个线程读取std :: map会有效吗?

注意:我目前正在使用visual studio 2008,但我希望这可以在大多数主要的STL实现中使用acros。

更新:编辑了const正确性的代码示例。

4 个答案:

答案 0 :(得分:16)

只要地图保持不变,这将在多个线程中起作用。您使用的地图事实上是不可变的,因此任何查找实际上都会在不会更改的地图中进行查找。

以下是相关链接:http://www.sgi.com/tech/stl/thread_safety.html

  

STL的SGI实现是   线程安全只在某种意义上说   同时访问不同的   容器是安全的,同时的   读取对共享容器的访问   很安全。如果多个线程访问a   单个容器,至少一个   线程可能会写,然后   用户负责确保   线程之间相互排斥   在容器访问期间。

你属于“共享容器的同时读取访问”类别。

注意:这适用于SGI实施。您需要检查是否使用其他实现。在我看来广泛用作替代方案的两种实现中,STLPort具有内置的线程安全性。我不知道Apache的实现。

答案 1 :(得分:9)

应该没问题。 如果要记录/强制执行只读行为,可以使用const引用。

请注意,无法保证正确性(原则上,地图可以选择在调用find时重新平衡自己),即使您只使用const方法(一个真正有悖常规的实现可能会声明树可变) 。但是,这在实践中似乎不太可能。

答案 2 :(得分:3)

是的。

请参阅相关帖子,其中包含有关std :: set:

的相同问题

Is the C++ std::set thread-safe?

答案 3 :(得分:0)

用于MS STL实施

Thread Safety in the C++ Standard Library

以下线程安全规则适用于C ++标准库中的所有类-包括shared_ptr,如下所述。有时会提供更强的保证,例如,如下所述的标准iostream对象以及专门用于多线程的类型,如。

一个对象是线程安全的,可以从多个线程读取。例如,对于给定的对象A,可以安全地从线程1和线程2读取A。