我正在尝试创建一个线程安全的 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);
}
};
最佳答案
这是想多了。保护整个容器的单个互斥锁就足够了。但是如果你非要实现这种复杂的设计:
- 为您的全局容器互斥使用
std::shared_mutex
。 - 在锁定各自的哈希桶之前,各个 getter/putter 需要获取全局互斥体上的共享锁。
- Rehash 获得排他锁,它会阻止所有 getters/putters。
关于c++ - 重新哈希时锁定 HashMap ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58576227/