繁体   English   中英

如何以线程安全的方式使用`std::unordered_map`?

[英]How to use `std::unordered_map` in a thread-safe way?

我做了什么

我的想法是包装std::unordered_map ,并为每个操作锁定它。 它看起来像这样(我将只留下一个操作,以免混淆问题):

template<class Key, class T>
class thread_safe_unordered_map {
   public:
    T &operator[](const Key &key) {
        std::lock_guard<std::mutex> lock{m_mutex};
        return m_underlying[key];
    }

   private:
    std::unordered_map<Key, T> m_underlying;
    std::mutex                 m_mutex;
};

但是后来我想到了这一点,现在我不知道如何正确地做到这一点。

想象一下这种情况。

线程1:调用operator[]写
线程 2:调用 operator[] 从中读取

两者都做自己的事情。 现在,因为 operator[] 返回一个引用,并且它们都将作用于同一个引用,我认为这仍然可能是数据竞争。 这是正确的吗?

我现在的想法

因为这个

所有 const 成员函数都可以被同一容器上的不同线程并发调用。 另外,成员函数begin()、end()、rbegin()、rend()、front()、back()、data()、find()、lower_bound()、upper_bound()、equal_range()、 at(),并且,除了在关联容器中,operator[] 出于线程安全的目的表现为 const。

我有这个问题。 在线程上使用at()是否正确,并且被锁定的是映射值?

现在,因为 operator[] 返回一个引用,并且它们都将作用于同一个引用,我认为这仍然可能是数据竞争。 这是正确的吗?

假设T不是线程安全类型,这是正确的。

这不是容器操作中的数据竞争,而是使用类型T的对象中的数据竞争。

我有这个问题。 在线程上使用 at() 是否正确

如果您只调用限定at的常量,那么您永远不会获得非常量引用,因此无法修改任何元素的值。 如果您不修改这些值,则不会发生数据竞争。

如果您使用限定at ,则在描述的数据竞争方面没有区别。

PS 你会发现你不能有任何同步的非常量成员函数,因为锁定互斥体需要修改。 你可以使用mutable来解决这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM