线程安全读取类成员向量,而无需复制

时间:2018-11-26 23:59:01

标签: c++ multithreading locking mutex

假设我有一堂课:

class A
{
   private:
   std::vector<MyObject> history;
   std::mutex historyLock;
}

该类初始化了多个线程,这些线程获取互斥量并写入历史向量。假设然后我有另一个班级想要阅读该列表:

class B
{
   public:
   B(A instanceA) 
   {
      // I want to read the list here in a thread safe way
   }
}

我的直觉告诉我在class A中公开一个名为GetHistory()的方法,该方法将锁定互斥锁,复制列表并返回副本。

是否有一种方法可以读取B类中的列表而不会产生复制操作的费用?

1 个答案:

答案 0 :(得分:2)

有几种方法可以解决此类问题。一种方法是使用更复杂的结构来存储您的历史记录,例如不可变的向量。 (一个不变的向量将迭代性能换成廉价的副本。)但是,仅使用标准C ++,我认为最简单的方法是向接受回调的类A添加遍历成员函数模板:

template <class F> void TraverseHistory(F&& callback)
{
  std::lock_guard guard{ historyMutex };
  for (auto const& item : history)
  {
    callback(item);
  }
}

如果您不想使用功能模板,也可以使用std::function

void TraverseHistory(std::function<void(MyObject const&)> const& callback);

另一种选择是将对整个向量的引用传递给您的回调。通过这种方法,功能模板将如下所示:

template <class F> void ReadHistory(F&& callback)
{
  std::lock_guard guard{ historyMutex };
  callback(std::as_const(history));
}