1

我知道只要不需要调整大小,就可以读取一些单元格并同时写入 STL 向量的不同单元格。我想知道是否允许同时获取某些键的值并同时将新的键值对插入 Visual C++ 2010 中的 STL 映射,如果我保证每个线程访问/插入不同的键。

来自 http://www.cplusplus.com/reference/map/map/operator[]/:

数据竞赛:

容器被访问,并且可能被修改。该函数访问一个元素并返回一个可用于修改其映射值的引用。同时访问其他元素是安全的。如果该函数插入一个新元素,则在容器中同时迭代范围是不安全的。

所以这说明如果我插入一个新元素,我就不能遍历容器。问题是访问不同的元素是否需要遍历容器。那这样安全吗?

如果我保证容器的大小永远不会超过 N 是否安全?然后也许地图的内部数据结构可以预先分配并保持不变——就像向量的内部结构一样,只要向量没有调整大小。

我知道有可用的 map 的线程安全实现,但它们可能要慢得多,所以我想知道标准 map 对我来说是否足够,因为我正在修改的代码是我的应用程序中的热点。

谢谢, 迈克尔

4

1 回答 1

5

I'm wondering if it's allowed to concurrently get values for some keys and in the same time inserting new key-value pairs to the STL map in Visual C++ 2010, if I guarantee that each thread accesses/inserts a different key.

No, it is not allowed. Lookup involves traversal of internal data structures (for std::map common approach for internal representation is binary search tree like Red–black tree). On the other hand insert modifies internal structures.

If simultaneous lookups and inserts would be thread-safe, then each access, even in single-thread environment, would involve high syncronization cost for operations, which contradicts C++ princple - "you do pay for what you don't use".

Thread Safety in MSVC 2010:

If a single object is being written to by one thread, then all reads and writes to that object on the same or other threads must be protected. For example, given an object A, if thread 1 is writing to A, then thread 2 must be prevented from reading from or writing to A.

That said, if you already have reference to element before insert operations in other thread - it would be safe to access element via that reference, because object is not moved during internal rebalancing.

ISO C++11 23.2.4/9:

The insert and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.


MSVC 2012 (but not MSVC 2010) has concurrency::concurrent_unordered_map associative container (note it is unordered which makes it similar to std::unordered_map, i.e. it requires hash and equality for keys rather than strict weak ordering):

The concurrent_unordered_map class is a concurrency-safe container that controls a varying-length sequence of elements of type std::pair<const _Key_type, _Element_type>. The sequence is represented in a way that enables concurrency-safe append, element access, iterator access, and iterator traversal operations.


Intel TBB library has similar container - tbb::concurrent_unordered_map:

Template class for associative container that supports concurrent insertion and traversal.

于 2013-07-11T19:47:58.160 回答