Solution 1:

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.

Solution 2:

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

Solution 3:

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.

Solution 4:

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

Solution 5:

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.