简体   繁体   English

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

[英]Thread safety of std::map for read-only operations

I have a std::map that I use to map values (field ID's) to a human readable string.我有一个 std::map 用于将值(字段 ID)映射到人类可读的字符串。 This map is initialised once when my program starts before any other threads are started, and after that it is never modified again.当我的程序在启动任何其他线程之前启动时,此映射会被初始化一次,之后就不再被修改。 Right now, I give every thread its own copy of this (rather large) map but this is obviously inefficient use of memory and it slows program startup.现在,我给每个线程自己的这个(相当大)映射的副本,但这显然是内存的低效使用,并且会减慢程序启动速度。 So I was thinking of giving each thread a pointer to the map, but that raises a thread-safety issue.所以我想给每个线程一个指向地图的指针,但这引发了一个线程安全问题。

If all I'm doing is reading from the map using the following code:如果我所做的只是使用以下代码从地图中读取:

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 = "";
}

Will this work or are there issues with reading a std::map from multiple threads?这会起作用还是从多个线程读取 std::map 有问题?

Note: I'm working with visual studio 2008 currently, but I'd like this to work acros most main STL implementations.注意:我目前正在使用 Visual Studio 2008,但我希望它适用于大多数主要的 STL 实现。

Update: Edited code sample for const correctness.更新:编辑代码示例以确保常量正确性。

This will work from multiple threads as long as your map remains the same.只要您的地图保持不变,这将适用于多个线程。 The map you use is immutable de facto so any find will actually do a find in a map which does not change.您使用的地图事实上是不可变的,因此任何查找实际上都会在不会更改的地图中进行查找。

Here is a relevant link: http://www.sgi.com/tech/stl/thread_safety.html这是一个相关的链接: http : //www.sgi.com/tech/stl/thread_safety.html

The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses to distinct containers are safe, and simultaneous read accesses to to shared containers are safe. STL 的 SGI 实现是线程安全的,仅在对不同容器的同时访问是安全的,对共享容器的同时读取访问是安全的意义上。 If multiple threads access a single container, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads during the container accesses.如果多个线程访问单个容器,并且至少有一个线程可能会写入,则用户负责确保容器访问期间线程之间的互斥。

You fall into he "simultaneous read accesses to shared containers" category.您属于“对共享容器的同时读取访问”类别。

Note: this is true for the SGI implementation.注意:这适用于 SGI 实现。 You need to check if you use another implementation.您需要检查是否使用其他实现。 Of the two implementations which seem widely used as an alternative, STLPort has built-in thread safety as I know.在这两种似乎被广泛用作替代方案的实现中,据我所知,STLPort 具有内置的线程安全性。 I don't know about the Apache implementation though.我不知道 Apache 的实现。

It should be fine.应该没问题。 You can use const references to it if you want to document/enforce read-only behaviour.如果您想记录/强制执行只读行为,您可以使用对它的const引用。

Note that correctness isn't guaranteed (in principle the map could choose to rebalance itself on a call to find ), even if you do use const methods only (a really perverse implementation could declare the tree mutable).请注意,不能保证正确性(原则上地图可以选择在调用find重新平衡自身),即使您只使用 const 方法(一个非常不正常的实现可以声明树可变)。 However, this seems pretty unlikely in practise.然而,这在实践中似乎不太可能。

Yes it is.是的。

See related post with same question about std::set:请参阅有关 std::set 的相同问题的相关帖子:

Is the C++ std::set thread-safe? C++ std::set 线程安全吗?

For MS STL implementation用于 MS STL 实现

Thread Safety in the C++ Standard Library C++ 标准库中的线程安全

The following thread safety rules apply to all classes in the C++ Standard Library—this includes shared_ptr, as described below.以下线程安全规则适用于 C++ 标准库中的所有类——包括 shared_ptr,如下所述。 Stronger guarantees are sometimes provided—for example, the standard iostream objects, as described below, and types specifically intended for multithreading, like those in .有时会提供更强的保证——例如,标准 iostream 对象,如下所述,以及专门用于多线程的类型,如 .

An object is thread-safe for reading from multiple threads.一个对象是线程安全的,可以从多个线程中读取。 For example, given an object A, it is safe to read A from thread 1 and from thread 2 simultaneously.例如,给定一个对象 A,同时从线程 1 和线程 2 读取 A 是安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM