D
,我想将(K, V)
对放入void save(K, V)
将内容为K
的文件名V
保存到目录D
D
是定义C
函数的类save
的字段void save(K, V)
的调用应该同时运行
tbb::task
进行并发save(K, V1)
和save(K, V2)
,则结果应该是D
中名为K
的文件,其内容等于< em> V1
或 V2
(但未损坏)H
映射到K
std::size_t
N > 1
C
提供一组互斥tbb::mutex mutex_map[N]
void save(K, V)
等待获取mutex_map[H(K) % N]
上的锁以执行其文件写入tbb
数据结构已经封装了这个互斥映射的概念?
std::map<TKey, tbb::mutex>
之类的东西,但接口会同时显示每个可能的键的外观,并同时具有相关的互斥锁。答案 0 :(得分:2)
是的,这是一种非常明智的做法。我想不出另一种选择(除了使用std::mutex
代替tbb:mutex
之类的简单替代方案。)
与您认为同时锁定的互斥锁数量相比,您应该选择N
大。 birthday paradox表示如果您希望 k 线程同时尝试锁定,则至少有一次虚假哈希冲突的概率大于50%,直到您获得N >
0(K 2 )
我不知道tbb数据结构就像互斥体地图。但内部我相信tbb :: malloc使用你建议的技巧(线程被随机分配给独立的malloc数据结构),并且实现了tbb :: concurrent_hash_map,这样就有一个互斥锁哈希桶。
答案 1 :(得分:0)
#include <vector>
#include <functional>
#include <tbb/mutex.h> //could of course use std::mutex instead, if available
template <typename Key, typename Hash = std::hash<Key>>
class mutex_map
{
public:
typedef Key key_type;
typedef tbb::mutex value_type;
static const std::size_t default_bucket_count = 16;
private:
std::vector<value_type> mutexes;
Hash hash;
public:
mutex_map(
std::size_t bucket_count = default_bucket_count,
const Hash& hash = Hash())
: hash(hash)
{
mutexes.resize(bucket_count);
}
std::size_t size() const
{
return mutexes.size();
}
value_type& get(const Key& key)
{
auto n = hash(key) % size();
n += (n < 0) * size();
return mutexes[n];
}
};