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

posted @ 2019-10-26 06:00  約束の空  阅读(201)  评论(0编辑  收藏  举报