对于 ~95% 写入/5% 读取线程安全的无序列图,有没有一个简单的解决方案?



我希望实现一个具有 2 个写入器和多个读取器的简单结构映射。为了使它线程安全,我目前正在使用带有唯一锁的互斥锁(我的代码如下(。只会对结构进行插入和编辑操作,而不会擦除。

但是,由于写入操作将比读取操作频繁得多(大约 ~1m 写入操作与同一时间段内的 15-20,000 次读取操作(,我担心使用唯一锁会影响读取操作的性能。

我想知道是否有更好/更简单的方法来为我的问题实现简单的并发映射?例如,每次执行写入/读取操作时,只锁定结构本身而不是整个映射会更好吗?

我已经研究了英特尔TBB并发无序列图和潘兴的Junction图,但如果可能的话,我宁愿坚持只使用STL。

我正在使用 C++11,因此shared_lock不可用。我考虑使用 boost::shared_lock 进行读取操作,但我从这篇文章中了解到,锁定shared_mutex的成本高于普通成本。

编辑:在注释中编辑代码发布讨论。

#include <mutex>
struct Foo
{
double bar1 = 0;
long bar2 = 0;
};
typedef std::shared_ptr<Foo> FooPtr;
class FooMap
{
std::mutex mMutex;
std::unordered_map<long, FooPtr> mMap;
public:
FooPtr get(long const& key) 
{    
return mMap[key];
}
void set(long const& key, double a, long b) 
{
std::unique_lock<std::mutex> lock(mMutex);
mMap[key]->bar1 = a;
mMap[key]->bar2 = b;
}

};

好吧,我放弃了...恐怕你的代码已经偏离了我的想法。这就是我真正建议的,你写到共享对象的新实例中来创建新的foo:

#include <mutex>
struct Foo
{
double bar1 = 0;
long bar2 = 0;
};
typedef std::shared_ptr<Foo> FooPtr;
typedef std::shared_ptr<const Foo> CFooPtr;
class FooMap
{
std::mutex mMutex;
std::unordered_map<long, FooPtr> mMap;
public:
CFooPtr get(long const& key) 
{    
auto found = mMap.find(key);
if (found == mMap.end())
{
return nullptr;
}  
return found->second;
}
void set(long const& key, double a, long b) 
{
FooPtr tmp = make_shared<Foo>({a,b});
{
std::unique_lock<std::mutex> lock(mMutex);
mMap[key].swap(tmp);
}
// previous entry contents are destroyed outside mutex
}
};

在这里,您可以找到仅使用 STL 的无锁哈希映射设计 https://shlomisteinberg.com/2015/09/28/designing-a-lock-free-wait-free-hash-map/

声称在繁重的写入方面比 TBB 更好。

相关内容

最新更新