简体   繁体   中英

How to individually lock unordered_map elements in C++

I have an unordered_map that I want to be accessible by multiple threads but locking the whole thing with a mutex would be too slow.

To get around this I put a mutex in each element of the unordered_map :

class exampleClass{
    std::mutex m;
    int data;
};

std::unordered_map<int,exampleClass> exampleMap;

The issue is I'm unable to safely erase elements, because in order to destroy a mutex it must be unlocked but if it's unlocked then another thread could lock it and be writing to or reading the element during destruction.

unordered_map is not suitable for fine-grained parallelism. It is not legal to add or remove elements without ensuring mutual exclusion during the process.

I would suggest using something like tbb::concurrent_hash_map instead, which will result in less lock contention than locking the map as a whole. (There are other concurrent hash table implementations out there; the advantage of TBB is that it's well-supported and stable.)

@Sneftel's answer is good enough.

But if you insist on using std::unordered_map, I suggest you two use one mutex to protect the insertion/deletion of the map, and another mutex for each element for modifying the element.

class exampleClass{
    std::mutex m;
    int data;
};

std::unordered_map<int,exampleClass> exampleMap;
std::mutex mapLock;

void add(int key, int value) {
    std::unique_lock<std::mutex> _(mapLock);
    exampleMap.insert({key, value});
}
void delete(int key) {
    std::unique_lock<std::mutex> _(mapLock);
    auto it = exampleMap.find(key);
    if (it != exampleMap.end()) {
        std::unique_lock<std::mutex> _1(it->m);
        exampleMap.erase(it);
    } 
}

These should perform better for a big lock on the whole map if delete is not a frequent operation.

But be careful of these kinds of code, because it is hard to reason and to get right.

I strongly recommend @Sneftel's answer.

You have the following options:

  1. Lock the entire mutex
  2. Use a container of shared_ptr so the actual class can be modified (with or without a mutex) unrelated to the container.

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