Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unordered_map thread safety

People also ask

Is C++ map thread safe?

It isn't thread safe, insert from two threads and you can end up in an inconstant state.

Is unordered_map stable?

Technically no, they are not guaranteed to be in any particular order. In practice however, given that you use deterministic hash function, what you want to do should be fine. you can reasonably expect that name-value pairs in map1 and map2 go in the same order.

Is order maintained in unordered_map?

No, it is not possible. Usage of std::unordered_map doesn't give you any guarantee on element order. If you want to keep elements sorted by map keys (as seems from your example) you should use std::map . If you need to keep list of ordered pairs you can use std::vector<std::pair<std::string,int>> .

Are duplicates allowed in unordered_map?

Because unordered_map containers do not allow for duplicate keys, this means that the function actually returns 1 if an element with that key exists in the container, and zero otherwise.


STL containers are designed so that you are guaranteed to be able to have:

A. Multiple threads reading at the same time

or

B. One thread writing at the same time

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.

http://eel.is/c++draft/res.on.data.races#3 is the part of the standard which guarantees the ability to concurrently use const functions on different threads. http://eel.is/c++draft/container.requirements.dataraces specifies some additional non-const operations which are safe on different threads.


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.

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)."

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.

I read somewhere that the C++ Standard says the behavior will be undefined, but is that all?

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?

It sounds good, but I've never used it myself so I can't offer an opinion.


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...


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.


std::unordered_map is a good fit for some multi-threaded situations.

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.