ConcurrentHashMap
下图是Java里的概念,其中 Hashtable 和 SynchronizedMap 都是对整个map加锁,所以多个thread没法同时修改。
ConcurrentHashMap 则允许多个thread同时访问不同的entry,即如果thread操作的key不同,这些thread是可以同时读写的。如果多个thread访问同一个key,这里就类似reader-writer lock。
用Seperate Chaining来实现hashmap,并对每个entry都设置一个reader-writer lock,即C++17里的shared_mutex。
注意vector容器如果调用resize或者别的需要copy的函数,会报错,因为mutex不是moveable的。
https://stackoverflow.com/questions/16465633/how-can-i-use-something-like-stdvectorstdmutex
#include "bits/stdc++.h" using namespace std; struct HashNode { int key; int value; HashNode(int k, int v):key(k),value(v){} }; class HashMap { vector<list<HashNode>> v; vector<shared_mutex > mtxs; int capacity; public: HashMap(int cap){ capacity = cap; v.resize(capacity); vector<shared_mutex> tmp(capacity); mtxs.swap(tmp); } int hashFunction(int key){ return key%capacity; } void insert(int key, int value){ int hashIndex=hashFunction(key); unique_lock<shared_mutex> writeLock(mtxs[hashIndex]); auto &cur_list=v[hashIndex]; for (auto it=cur_list.begin();it!=cur_list.end();++it){ if (it->key==key){ it->value=value; return; } } cur_list.emplace_back(key,value); } void erase(int key){ int hashIndex=hashFunction(key); unique_lock<shared_mutex> writeLock(mtxs[hashIndex]); auto &cur_list=v[hashIndex]; for (auto it=cur_list.begin();it!=cur_list.end();++it){ if (it->key==key){ cur_list.erase(it); return; } } } int at(int key){ int hashIndex=hashFunction(key); shared_lock<shared_mutex> readLock(mtxs[hashIndex]); auto &cur_list=v[hashIndex]; for (auto it=cur_list.begin();it!=cur_list.end();++it){ if (it->key==key){ return it->value; } } return INT_MIN; // not found } void display(){ for (int i=0;i<capacity;++i){ cout << i << ": "; for (auto x:v[i]) cout<<x.key<<' '; cout << endl; } } }; int main() { HashMap hashmap(7); vector<int> to_insert{15,11,27,8}; for (int x:to_insert) hashmap.insert(x,x); hashmap.display(); cout<<hashmap.at(8); hashmap.erase(8); hashmap.display(); cout<<hashmap.at(8); return 0; }
Reference
https://codepumpkin.com/hashtable-vs-synchronizedmap-vs-concurrenthashmap/
https://stackoverflow.com/questions/16465633/how-can-i-use-something-like-stdvectorstdmutex