我们是否需要在std :: map <k,v =“”> :: find函数周围锁定互斥锁?

时间:2018-04-09 15:34:26

标签: c++ multithreading boost mutex

我们在这里:

template<typename TK, typename TV>
class MetaAssociator
{
public:

   void Set(TK key, TV const & value)
   {
      boost::lock_guard<boost::mutex> lock(m_Mutex);
      m_Map[key] = value;
   }

   TV Get(TK key) const
   {
      boost::lock_guard<boost::mutex> lock(m_Mutex); // this one
      std::map<TK,TV>::const_iterator iter = m_Map.find(key);
      return iter == m_Map.end() ? TV() : iter->second;
   }

private:
   mutable boost::mutex m_Mutex;
   std::map<TK,TV> m_Map;
};

我们真的需要在get函数中锁定互斥锁吗?我们只提供只读访问权限。如果我们不怎么办?

5 个答案:

答案 0 :(得分:5)

是的,我们需要它。

假设有2个线程A和B:

  • 主题A正在设置值。
  • 线程B同时读取此值。

此处可以生成数据争用条件,包括分段错误(线程B正在尝试使用不再存在的对象)。

我们可以使用互斥锁来保护这些部分(如您的示例中所示)。另一种选择是使用read and write lock。读写锁的优点是允许并发读访问。

答案 1 :(得分:3)

是。在并行编程101中,您了解到您的流程可以随时中断,包括您在iter=函数中选择了Get。如果另一个进程在第一个进程正在休眠时执行带有Set函数的插入,则iter变量会损坏,因为它现在正在引用可能已移动的元素(由于任何原因)

答案 2 :(得分:3)

从两个执行线程同时访问同一个对象,至少在访问是一个修改时,是未定义行为的典型示例,在这种情况下是数据竞争。

正因为如此,除非你有其他方法可以保证Set永远不会与Red同时调用(虽然同步放在程序的其他部分),你需要一个同步原语。但是,正如其他评论员所说,std::shared_mutex可能更适合读/写类型的锁。

答案 3 :(得分:2)

问题是双重的。

  1. 锁定自身:是的,它需要潜在的重新排序,部分读/写和其他并行的事情
  2. 数据安全:您通过Get()获得了结果,然后从地图中删除了该条目(保护与getter和setter相同),然后尝试访问本地存储的结果。那会发生什么?例如,如果电视只是指向某个东西的原始指针,那么你手中的死链接就会遇到麻烦......

答案 4 :(得分:1)

因为某个过程可以在另一个过程正在阅读时写入。

检查经典的“读者作家问题”