带有front()+ pop()的线程安全队列

时间:2015-02-09 19:35:27

标签: c++11 thread-safety

我创建了一个线程安全队列(参见代码)。该类似乎工作,但现在我想使组合front()和pop()线程安全,使线程首先获取元素,然后确保删除相同的元素。我可以提出一些解决方案,但它们对于用户方而言并不优雅,否则强大的异常安全保障将会丢失。

第一个解决方案是用户只需要锁定ThreadQueueu而不是调用front()和pop()并解锁ThreadQueue。但是,该类的整个想法是用户不必关心线程安全性。

第二个解决方案是将队列锁定在重载函数front()中,并仅在pop()中解锁。但是,在这种情况下,不允许用户只调用front()或pop(),而不是用户友好..

我提出的第三个选项是在类(frontPop)中创建一个公共函数,它返回前面的元素并将其删除。但是在这种情况下,异常安全性已经消失。

什么是用户友好(优雅)并保持异常安全的解决方案?

class ThreadQueue: private std::queue<std::string>
{
  mutable std::mutex d_mutex;

  public:
    void pop()
    {
      lock_guard<mutex> lock(d_mutex);
      pop();
    }

    std::string &front()
    {
      lock_guard<mutex> lock(d_mutex);
      return front();
    }

    // All other functions

  private:

};

1 个答案:

答案 0 :(得分:4)

通常的解决方案是提供前后组合。 pop,接受存储弹出值的引用,如果弹出一个值,则返回bool true

bool pop(std::string& t) {
  lock_guard<mutex> lock(d_mutex);

  if (std::queue<std::string>::empty()) {
    return false;
  }

  t = std::move(std::queue<std::string>::front());
  std::queue<std::string>::pop();
  return true;
}

移动分配抛出的任何异常都发生在修改队列之前,维护值类型移动赋值运算符提供的异常保证。