对于〜95%写入/ 5%读取的线程安全无序映射,是否有简单的解决方案?

时间:2018-08-21 10:42:02

标签: c++ multithreading c++11 parallel-processing stl

我正在寻找一个由2个作者和多个读者组成的简单结构的地图。为了使其具有线程安全性,我目前正在使用具有唯一锁的互斥锁(下面的代码)。在结构上将只有插入和编辑操作,而不会擦除。

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

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

我研究了Intel TBB并发无序映射和Pershing的Junction映射,但是如果可能的话,我宁愿坚持使用STL。

我正在使用C ++ 11,因此shared_lock不可用。我打算对读取操作使用boost :: shared_lock,但是从this post中我了解到,锁定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;
    }

};

2 个答案:

答案 0 :(得分:1)

好吧,我放弃...恐怕您的代码与我的想法相去甚远。这是我真正的建议,您在其中写入共享库的新实例以创建新的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
  }
};

答案 1 :(得分:0)

在这里,您只能在以下位置找到带有STL的无锁哈希映射的设计: https://shlomisteinberg.com/2015/09/28/designing-a-lock-free-wait-free-hash-map/

要求在大量写入时要优于TBB。