There are two threads where one will insert into the map and the other will find
from the map.
map<string,object>* mapA;
If thread A will insert the configuration object into the Map w.r.t the string key.
Where the thread B will try to find with the same string key. If not present it will try again until the string key is found by it.
Will it cause a crash or data corruption in the process , if thread A inserts at the same time when thread B is read the key ? Is there synchronization needed here?
While testing with a sample application i dint face any type of crash or corruption
The container can be accessed without any locking mechanism, only if all the threads involved are reader threads.
The thread safety of stl containers has been discussed here:
Why does the C++ STL not provide a set of thread-safe containers?
Quoting the spec:
23.2.2 Container data races
"implementations are required to avoid data races when the contents of the contained object in different elements in the same container, excepting vector, are modified concurrently."
In short, in your case, since both insert and find are involved from different threads, locking is needed.
Use-case where locking is needed: If you have a datastructure on which insert and find are being performed intermittently/concurrently, then locking is needed .
Use-case where locking is not needed: If you have a datastructure that is populated at one shot and then subsequently, only finds are performed then locking is not needed.
Here is the source code:
STL map uses rb-tree internally.so, here is a look at rb-tree find method.
template <class _Key, class _Value, class _KeyOfValue,
class _Compare, class _Alloc>
typename _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::iterator
_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::find(const _Key& __k)
{
_Link_type __y = _M_header; // Last node which is not less than __k.
_Link_type __x = _M_root(); // Current node.
while (__x != 0)
if (!_M_key_compare(_S_key(__x), __k))
__y = __x, __x = _S_left(__x);
else
__x = _S_right(__x);
iterator __j = iterator(__y);
return (__j == end() || _M_key_compare(__k, _S_key(__j._M_node))) ?
end() : __j;
}
As seen, there is no lock used and it makes sense since the overhead of lock is not really needed/desired for non-threaded applications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With