我们需要在 std::map<K, V>::find 函数周围锁定互斥量吗?

Do we need to lock mutex around std::map<K, V>::find function?

我们在这里:

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 函数中锁定 mutex 吗?我们仅提供只读访问权限。如果我们不这样做呢?

因为一些进程可以在另一个正在读的时候写。

查经典"Readers Writers Problem"

从两个执行线程同时访问同一个对象,当至少 on access 是一个修改时,是未定义行为的典型示例,在本例中是数据竞争。

因此,除非你有其他方法来保证 Set 永远不会与 Red 同时调用(尽管同步放在程序的其他部分)你确实需要一个同步原语那里。但是,正如其他评论员所建议的那样,std::shared_mutex 可能更适合 read/write 类型的锁。

是的,我们需要它。

假设有 2 个线程 A 和 B:

  • 线程A正在设置值。
  • 线程B正在同时读取这个值。

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

我们可以使用互斥锁来保护这些部分(就像在您的示例中一样)。另一种选择是使用 read and write lock。 read-write 锁的优点是允许并发 read-access.

问题是two-fold。

  1. 自我锁定:是的,由于潜在的重新排序、部分 read/writes 和其他类似的事情,它是必需的
  2. 数据安全:您通过 Get() 获得了一个结果,然后从映射中删除了该条目(与 getter 和 setter 的保护方式相同),然后尝试访问存储的结果本地。那应该怎么办?例如,如果电视只是指向某物的原始指针,那么您手中的死 link 就会遇到麻烦...