C ++ Map并发插入和读取两个线程

时间:2015-09-28 04:35:49

标签: c++ multithreading dictionary synchronization

有两个线程,其中一个将插入到地图中,另一个将从地图中find

map<string,object>* mapA;

如果线程A将配置对象插入到字符串w.r.t中的字符串键。

线程B将尝试使用相同的字符串键查找。如果不存在,它将再次尝试,直到找到它的字符串键。

如果线程A在读取密钥B的同时插入线程A,是否会导致进程崩溃或数据损坏?这里需要同步吗?

使用示例应用程序进行测试时,我会面临任何类型的崩溃或损坏

2 个答案:

答案 0 :(得分:4)

只有当涉及的所有线程都是读者线程时,才能在没有任何锁定机制的情况下访问容器。

这里讨论了stl容器的线程安全性:

Why does the C++ STL not provide a set of thread-safe containers?

引用规范:

23.2.2集装箱数据竞赛

  

“实现是必需的,以避免数据争用时的内容   包含在同一容器中不同元素的对象,   除了矢量,同时修改。“

简而言之,在您的情况下,由于插入和查找都涉及不同的线程,因此需要锁定。

需要锁定的用例: 如果您有一个数据结构,间歇性地/同时执行插入和查找,则需要锁定。

不需要锁定的用例: 如果您有一次填充的数据结构,然后只执行查找,则不需要锁定。

以下是源代码:

STL map在内部使用rb-tree。这里是rb-tree查找方法。

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;
}

如图所示,没有使用锁,这是有道理的,因为非线程应用程序并不真正需要/期望锁的开销。

答案 1 :(得分:0)

基本上你不知道将会发生什么,STL将不承诺数据将为你从第一个线程读取而另一个进行插入。如果你想这样做,你需要锁定,因为你没有看到任何问题并不意味着它永远不会发生。