简体   繁体   中英

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. 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
Thread 2: Calls operator[] to read from it

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. Is this right?

My idea now

Because of this :

All const member functions can be called concurrently by different threads on the same container. 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.

I have this question. Would it be correct to use at() on the threads, and the thing that gets locked is the mapped value?

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. Is this right?

This is right assuming T isn't a thread-safe type.

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 .

I have this question. Would it be correct to use at() on the threads

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. 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.

PS You'll find that you wouldn't be able to have any synchronised non-const member functions because locking a mutex requires modification. You can get around that using mutable .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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