Thread-safety of c++ maps - c++

This is about thread safety of std::map. Now, simultaneous reads are thread-safe but writes are not. My question is that if I add unique element to the map everytime, will that be thread-safe?
So, for an example, If I have a map like this std:map<int, std::string> myMap
and I always add new keys and never modify the existing key-value, will that be thread-safe?
More importantly, will that give me any random run-time behavior?
Is adding new keys also considered modification? If the keys are always different while adding, shouldn't it be thread-safe as it modifies an independent part of the memory?
Thanks
Shiv

1) Of course not
2) Yes, I hope you'll encounter it during testing, not later
3) Yes, it is. The new element is added in a different location, but many pointers are modified during that.
The map is implemented by some sort of tree in most if not all implementations. Inserting a new element in a tree modifies it by rearranging nodes by means of resetting pointers to point to different nodes. So it is not thread safe

no, yes, yes. You need to obtain exclusive lock when modifying container (including insertion of new keys), though while there's no modification going on you can, of course, safely read concurrently.
edit: http://www.sgi.com/tech/stl/thread_safety.html might be of interest for you.

Related

How to implement a boost::unordered_map with websocketpp::connection_hdl as key?

For my application, it is much more convenient and logical to hold a map of websocketpp::connection_hdls as keys in a map, but I've found that this could be potentially dangerous since they are weak_ptrs.
However, it's been claimed that a boost::unordered_map may not break if a weak_ptr key expires.
Is that true? If so, how can one be constructed to hold connection_hdls as keys as well as be inserted, erased, and found/counted? Also, what is necessary to be able to loop through them, such as with a for?
This is currently beyond my skillset, so I'm unsure of what I'm looking at.
boost::unordered_map could be slow on iteration, thus, I would suggest that you could store all websocketpp::connection_hdl in a std::vector. For the map you can use pointers as keys: boost::unordered_map<websocketpp::connection_hdl*, X>

C++ do we need mutex when using map?

I have two threads, one is inserting and another is deleting an entry in the map. I am wondering whether I have a mutex around these function calls? And also one thread incrementing a counter inside this map and the other decrementing that counter. Do I need mutex for that as well?
Thanks,
Changes to the map itself (insertions, deletions) need to be synchronized. The same is true for traversal and lookup (i.e. begin(), find(), [], etc.).
Multiple threads can access different elements safely, though.
If you are incrementing and decrementing the SAME element in the map (or what may be the same element and you can't say for sure), then you need to have some sort of synchronisation. You could use an std::atomic<int> to avoid having to use a mutex tho'.
Any insert or remove in the tree will need to be protected with a mutex or similar - and of course, that also means that any access to the content of the tree needs to be protected in the same way, so if you use std::map<T>::iterator (at least for erase in the tree) will be invalidated. So you really need to ensure that no erase happens when you use any other access to the tree. This includes "ready-made" functions such as find.

Mutithreading accessing one std::map , will cause unsafe behavior?

If more than one thread access one map object, but, I can make sure any of these threads accessing will not have the same key, and the accessing is just like:
//find value by key
//if find
// erase the object or change the value
//else
// add new object of the key
Will the operation cause synchronization problem?
Yes, doing concurrent updates without proper synchronization may cause crashes, even if your threads access different keys: the std::map is based on trees, trees get rebalanced, so you can cause a write to a parent of a node with a seemingly unrelated key.
Moreover, it is not safe to perform read-only access concurrently with writing, or searching unlocked + locking on write: if you have threads that may update or delete nodes, you must lock out all readers before you write.
You will have concurrency problems if any of the threads inserts into the tree. STL map is implemented using a red-black tree (or at least that's what I'm familiar with — I don't know whether the Standard mandates red-black tree). Red-black trees may be rebalanced upon insert, which would lead to all sorts of races between threads.
Read-only access (absolutely no writers) would be fine, but keep in mind operator[] is not read-only; it potentially adds a new element. You'd need to use the find() method, get the iterator, and derefence it yourself.
Unless the docs (ie, the ISO C++11 standard) say it's thread-safe (and they don't), then that's it. Period. It's not thread-safe.
There may be implementations of a std::map that would allow this but it's by no means portable.
Maps are often built on red-black trees or other auto-balancing data structures so that a modification to the structure (such as inserting or deleting a key) will cause rebalancing.
You should wrap read and write operations on the map with something like a mutex semaphore, to ensure that synchronisation is done correctly.

thread-safe alternative for std::map?

I have a parallized loop and write access to a std::map. I would like to different parts of the map at the same time, i.e. I want to access map[a] and map[b] for a,b different. At I found out that this is not possible, I wonder, however, if there is a good alternative or how to achieve this in a different way!
I could be wrong, but I believe that modifying existing elements to a map is safe as long as you're not touching the same elements (as this does not modify the underlying structure of the map). So if you insert map[a] and map[b] ahead of time, your separate threads should be able to modify those existing elements.
That said, it's probably cleaner and safer just to use normal synchronization techniques such as mutexes to protect access to the map.
It is quite possible to mutate map[a] and map[b] separately, as long as you do not mutate the underling map.
If you wish to mutate an associative container concurrently, check out concurrent_unordered_map from PPL or TBB.
If possible, you could try giving each worker its own copy of the map and then merging the results. This way no locking would be needed at all.

Am I going to be OK for threading with STL given these conditions?

I have a collection of the form:
map<key, list<object> >
I only ever insert at the back of the list and sometimes I read from the entire map (but I never write to the map, except at initialization).
As I understand it, none of the STL containers are thread safe, but I can only really have a maximum of one thread per key. Am I missing anything in assuming I'll be pretty safe with this arrangement?
If the map is never modified at all during the multi-threaded scenario, then you're fine. If each thread looks at its own list, then that's thread-private data, so you're also fine.
Take care not to try and lookup keys with [] because that will insert (modify) if the key doesn't exist in the map yet.
However, I'm curious as to why you'd need this structure - why not keep a pointer/reference or the actual list object itself on the stack of each thread, given that it's private to each thread?
(If it's not, then you need proper synchronisation on the list.)
In fact you say you "read from the entire map" - presumably meaning that any random thread may try to iterate through any of the lists. So you definitely need to synchronise operations on the lists.
TBH as long as you put a critical section around any write and read it will work fine.