C++ unordered_map 线程安全
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9685486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
unordered_map thread safety
提问by questions
I am changing a single thread program into multi thread using boost:thread library. The program uses unordered_map as a hasp_map for lookups. My question is..
我正在使用 boost:thread 库将单线程程序更改为多线程。该程序使用 unordered_map 作为 hasp_map 进行查找。我的问题是..
At one time many threads will be writing, and at another many will be reading but not both reading and writing at the same time i.e. either all the threads will be reading or all will be writing. Will that be thread safe and the container designed for this? And if it will be, will it really be concurrent and improve performance? Do I need to use some locking mechanism?
一次有很多线程在写,而在另一次很多线程都在读,但不是同时读和写,即要么所有线程都在读,要么都在写。这会是线程安全的吗?为此而设计的容器?如果是,它真的会并发并提高性能吗?我需要使用一些锁定机制吗?
I read somewhere that the C++ Standard says the behavior will be undefined, but is that all?
我在某处读到 C++ 标准说行为将是未定义的,但仅此而已吗?
UPDATE: I was also thinking about Intel concurrent_hash_map. Will that be a good option?
更新:我也在考虑英特尔 concurrent_hash_map。这会是一个不错的选择吗?
回答by Lalaland
STL containers are designed so that you are guaranteed to be able to have:
STL 容器的设计确保您能够拥有:
A. Multiple threads reading at the same time
A. 多线程同时读取
or
或者
B. One thread writing at the same time
B. 一个线程同时写入
Having multiple threads writing is not one of the above conditions and is not allowed. Multiple threads writing will thus create a data race, which is undefined behavior.
多线程写入不是上述情况之一,是不允许的。因此,多线程写入会造成数据竞争,这是未定义的行为。
You could use a mutex to fix this. A shared_mutex (combined with shared_locks) would be especially useful as that type of mutex allows multiple concurrent readers.
您可以使用互斥锁来解决此问题。shared_mutex(与 shared_locks 结合)将特别有用,因为这种类型的互斥锁允许多个并发读取器。
http://eel.is/c++draft/res.on.data.races#3is the part of the standard which guarantees the ability to concurrently use const functions on different threads. http://eel.is/c++draft/container.requirements.dataracesspecifies some additional non-const operations which are safe on different threads.
http://eel.is/c++draft/res.on.data.races#3是标准的一部分,它保证了在不同线程上同时使用 const 函数的能力。 http://eel.is/c++draft/container.requirements.dataraces指定了一些额外的非常量操作,这些操作在不同线程上是安全的。
回答by Ida
std::unordered_map meets the requirements of Container (ref http://en.cppreference.com/w/cpp/container/unordered_map). For container thread safety see: http://en.cppreference.com/w/cpp/container#Thread_safety.
std::unordered_map 满足容器的要求(参考http://en.cppreference.com/w/cpp/container/unordered_map)。有关容器线程安全,请参阅:http: //en.cppreference.com/w/cpp/container#Thread_safety。
Important points:
要点:
- "Different elements in the same container can be modified concurrently by different threads"
- "All const member functions can be called concurrently by different threads on the same container. In addition, the member functions begin(), end(), rbegin(), rend(), front(), back(), data(), find(), lower_bound(), upper_bound(), equal_range(), at(), and, except in associative containers, operator[], behave as const for the purposes of thread safety (that is, they can also be called concurrently by different threads on the same container)."
- “同一个容器中的不同元素可以被不同的线程同时修改”
- "所有const成员函数都可以被同一个容器上的不同线程并发调用。另外,成员函数begin()、end()、rbegin()、rend()、front()、back()、data() 、 find()、lower_bound()、upper_bound()、equal_range()、at() 以及,除了在关联容器中,operator[] 出于线程安全的目的表现为 const(也就是说,它们也可以被称为由同一容器上的不同线程同时执行)。”
回答by Mike Seymour
Will that be thread safe and the container designed for this?
这会是线程安全的吗?为此而设计的容器?
No, the standard containers are not thread safe.
不,标准容器不是线程安全的。
Do I need to use some locking mechanism?
我需要使用一些锁定机制吗?
Yes, you do. Since you're using boost, boost::mutex
would be a good idea; in C++11, there's std::mutex
.
是的你是。由于您使用的是 boost,boost::mutex
这将是一个好主意;在 C++11 中,有std::mutex
.
I read somewhere that the C++ Standard says the behavior will be undefined, but is that all?
我在某处读到 C++ 标准说行为将是未定义的,但仅此而已吗?
Indeed, the behaviour is undefined. I'm not sure what you mean by "is that all?", since undefined behaviour is the worst possible kind of behaviour, and a program that exhibits it is by definition incorrect. In particular, incorrect thread synchronisation is likely to lead to random crashes and data corruption, often in ways that are very difficult to diagnose, so you would be wise to avoid it at all costs.
事实上,行为是未定义的。我不确定您所说的“仅此而已?”是什么意思,因为未定义的行为是最糟糕的行为,而显示它的程序根据定义是不正确的。特别是,不正确的线程同步很可能导致随机崩溃和数据损坏,通常是很难诊断的方式,因此您最好不惜一切代价避免它。
UPDATE: I was also thinking about Intel concurrent_hash_map. Will that be a good option?
更新:我也在考虑英特尔 concurrent_hash_map。这会是一个不错的选择吗?
It sounds good, but I've never used it myself so I can't offer an opinion.
听起来不错,但我自己从未使用过它,所以我无法提供意见。
回答by Tony Delroy
The existing answers cover the main points:
现有的答案涵盖了要点:
- you must have a lock to read or write to the map
- you could use a multiple-reader / single-writer lock to improve concurrency
- 您必须有锁才能读取或写入地图
- 您可以使用多读/单写锁来提高并发性
Also, you should be aware that:
此外,您应该注意:
using an earlier-retrieved iterator, or a reference or pointer to an item in the map, counts as a read or write operation
write operations performed in other threads may invalidate pointers/references/iterators into the map, much as they would if they were done in the same thread, even if a lock is again acquired before an attempt is made to continue using them...
使用较早检索的迭代器,或指向映射中项目的引用或指针,算作读或写操作
在其他线程中执行的写操作可能会使映射中的指针/引用/迭代器无效,就像它们在同一线程中完成时一样,即使在尝试继续使用它们之前再次获取锁...
回答by Chang
You can use concurrent_hash_map or employ an mutex when you access unordered_map. one of issue on using intel concurrent_hash_map is you have to include TBB, but you already use boost.thread. These two components have overlapped functionality, and hence complicate your code base.
您可以在访问 unordered_map 时使用 concurrent_hash_map 或使用互斥锁。使用英特尔 concurrent_hash_map 的问题之一是您必须包含 TBB,但您已经使用了 boost.thread。这两个组件具有重叠的功能,因此使您的代码库复杂化。
回答by Contango
std::unordered_map
is a good fit for some multi-threaded situations.
std::unordered_map
非常适合某些多线程情况。
There are also other concurrent maps from Intel TBB:
tbb:concurrent_hash_map
. It supports fine-grained, per-key locking for insert/update, which is something that few other hashmaps can offer. However, the syntax is slightly more wordy. See full sample code. Recommended.tbb:concurrent_unordered_map
. It is essentially the same thing, a key/value map. However, it is much lower level, and more difficult to use. One has to supply a hasher, a equality operator, and an allocator. There is no sample code anywhere, even in the official Intel docs. Not recommended.
tbb:concurrent_hash_map
. 它支持用于插入/更新的细粒度、按键锁定,这是其他哈希映射无法提供的。但是,语法稍微冗长一些。请参阅完整的示例代码。受到推崇的。tbb:concurrent_unordered_map
. 它本质上是一样的东西,一个键/值映射。但是,它的级别要低得多,并且更难使用。必须提供散列器、相等运算符和分配器。即使在英特尔官方文档中,也没有任何示例代码。不建议。