简体   繁体   English

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

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

What I have done我做了什么

I had the idea to wrap std::unordered_map , and the to lock it for every operation.我的想法是包装std::unordered_map ,并为每个操作锁定它。 And it looked something like this (I will just leave one operation to not clutter the question):它看起来像这样(我将只留下一个操作,以免混淆问题):

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

But then this crossed my mind, and now I dont know how to do it correctly.但是后来我想到了这一点,现在我不知道如何正确地做到这一点。

Imagine this situation.想象一下这种情况。

Thread 1: Calls operator[] to write线程1:调用operator[]写
Thread 2: Calls operator[] to read from it线程 2:调用 operator[] 从中读取

Both do their stuff.两者都做自己的事情。 Now, because operator[] returns a reference, and they both will act on the same reference, I think that this could still be a data race.现在,因为 operator[] 返回一个引用,并且它们都将作用于同一个引用,我认为这仍然可能是数据竞争。 Is this right?这是正确的吗?

My idea now我现在的想法

Because of this :因为这个

All const member functions can be called concurrently by different threads on the same container.所有 const 成员函数都可以被同一容器上的不同线程并发调用。 In addition, the member functions begin(), end(), rbegin(), rend(), front(), back(), data(), find(), lower_bound(), upper_bound(), equal_range(), at(), and, except in associative containers, operator[], behave as const for the purposes of thread safety.另外,成员函数begin()、end()、rbegin()、rend()、front()、back()、data()、find()、lower_bound()、upper_bound()、equal_range()、 at(),并且,除了在关联容器中,operator[] 出于线程安全的目的表现为 const。

I have this question.我有这个问题。 Would it be correct to use at() on the threads, and the thing that gets locked is the mapped value?在线程上使用at()是否正确,并且被锁定的是映射值?

Now, because operator[] returns a reference, and they both will act on the same reference, I think that this could still be a data race.现在,因为 operator[] 返回一个引用,并且它们都将作用于同一个引用,我认为这仍然可能是数据竞争。 Is this right?这是正确的吗?

This is right assuming T isn't a thread-safe type.假设T不是线程安全类型,这是正确的。

This isn't a data race in the operation of the container, but a data race in the use of the object of type T .这不是容器操作中的数据竞争,而是使用类型T的对象中的数据竞争。

I have this question.我有这个问题。 Would it be correct to use at() on the threads在线程上使用 at() 是否正确

If you only call the const qualified at , then you never get a non-const reference and thus cannot modify the value of any element.如果您只调用限定at的常量,那么您永远不会获得非常量引用,因此无法修改任何元素的值。 If you don't modify the values, then you don't have a data race.如果您不修改这些值,则不会发生数据竞争。

If you use the non-const qualified at , then there is no difference in regards to the described data race.如果您使用限定at ,则在描述的数据竞争方面没有区别。

PS You'll find that you wouldn't be able to have any synchronised non-const member functions because locking a mutex requires modification. PS 你会发现你不能有任何同步的非常量成员函数,因为锁定互斥体需要修改。 You can get around that using mutable .你可以使用mutable来解决这个问题。

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

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