c++ - 重新哈希时锁定 HashMap

标签 c++ multithreading c++11 hashmap mutex

我正在尝试创建一个线程安全的 HashMap 。我为散列映射中的每个存储桶提供了一个互斥 vector ,以支持散列映射中每个条目的读写锁。

但是,当我想重新散列 HashMap 时,我想锁定整个映射,以便在重新散列期间不会发生读/写。

我想我需要一个额外的互斥锁,但是我的 Gets/Puts 方法是否也需要获取这个互斥锁?如何仅在重新散列发生时阻止其他线程执行读取/写入操作,而在仅发生写入和读取操作时如何不相互阻塞?

这是我当前的哈希表类的样子:

template<typename K, typename T>
class HashTable {
    int num_buckets_;
    double threshold_ratio_;
    int num_elements_;
    vector<vector<pair<T, K>>> table_;
    vector<mutex> read_write_locks_;
    mutex mu_;

    int GetHash(const K& key) {
        return hash<K>{}(key) % num_buckets_;
    }

    void Rehash() {
        scoped_lock<mutex> lock(mu_);   // Lock the whole table?
        cout << "Threshold Value has been reached. Rehashing...\n";

        vector<vector<T>> new_table(2 * num_buckets_);
        num_buckets_ = 2 * num_buckets_;

        vector<mutex> new_mutexes(2 * num_buckets_);
        read_write_locks_.swap(new_mutexes);
        // TODO : Implementation
    }

public:
    explicit HashTable(int num_buckets) : num_buckets_(num_buckets), threshold_ratio_(0.75), num_elements_(0) {
        table_.resize(num_buckets);
        vector<mutex> temp(num_buckets);
        read_write_locks_.swap(temp);
    }

    void Put(const K& key, const T& val) {
        ++num_elements_;
        if (static_cast<double>(num_elements_) / num_buckets_ > threshold_ratio_) {
            Rehash();
        }
        int hash_val = GetHash(key);
        scoped_lock<mutex> write_lock(read_write_locks_[hash_val]);
        cout << "Putting Key: " << key << ", Hash: "<< hash_val << "  with Value: " << val << '\n';
        table_[hash_val].push_back({val, key}); //TODO: For existing keys it should replace the value, not create a new entry
    }

    T Get(const K& key) {
        int hash_val = GetHash(key);
        scoped_lock<mutex> read_lock(read_write_locks_[hash_val]);

        if (table_[hash_val].size() >= 1) {
            for (const auto& elem : table_[hash_val]) {
                if (elem.second == key) {
                    cout << "Key: " << key << " gets value: " << elem.first << '\n';
                    return elem.first;
                }
            }
        }
        cerr << "Unable to find key in hash table. Terminating Program. \n";
        exit(EXIT_FAILURE);
    }
};

最佳答案

这是想多了。保护整个容器的单个互斥锁就足够了。但是如果你非要实现这种复杂的设计:

  1. 为您的全局容器互斥使用 std::shared_mutex
  2. 在锁定各自的哈希桶之前,各个 getter/putter 需要获取全局互斥体上的共享锁。
  3. Rehash 获得排他锁,它会阻止所有 getters/putters。

关于c++ - 重新哈希时锁定 HashMap ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58576227/

相关文章:

c++ - 如何替换文本文件中的一行?

c# - 线程本地存储和本地方法变量

c++ - 迭代不同的类型

c++ - 如何更改 boost 线程限制?

c++ - 我可以将 final 关键字应用于 C++11 中的 POD(标准布局)结构吗?我是不是该?

c++ - 在 C++ 中使用::每次

Python 线程没有被垃圾收集

multithreading - mpsc::Sender<T<'a>> 和线程的 Rust 生命周期

c++ - 我需要检查是否从 operator=? 抛出异常?

c++ - 一个普通的 `char` 可能有陷阱值吗?