std :: condition_variable线程安全吗?

时间:2017-10-19 03:36:31

标签: c++ multithreading c++11

我有一些像这样的代码:

std::queue<myData*> _qDatas;
std::mutex _qDatasMtx;

生成器功能

void generator_thread()
{
  std::this_thread::sleep_for(std::chrono::milliseconds(1));
  {
    std::lock_guard<std::mutex> lck(_qDatasMtx);
    _qData.push(new myData);
  }
  //std::lock_guard<std::mutex> lck(cvMtx); //need lock here?
  cv.notify_one();
}

消费者功能

void consumer_thread()
{
  for(;;)
  {
    std::unique_lock lck(_qDatasMtx);
    if(_qDatas.size() > 0)
    {
       delete _qDatas.front();
       _qDatas.pop();
    }
    else
      cv.wait(lck);
  }
}

因此,如果我有几十个生成器线程和一个消费者线程,在每个线程中调用cv.notify_one()时是否需要互斥锁?

std :: condition_variable线程安全吗?

2 个答案:

答案 0 :(得分:5)

notify_one可以在没有锁定的情况下从多个线程调用。

但是,为了使正常操作工作并且没有通知&#34;滑过&#34;,您必须保持锁定条件变量在您修改虚假唤醒警卫的点与/之间保护。或打包条件变量检查读取,以及通知它的点。

您的代码似乎通过了该测试。但是这个版本更清楚:

std::unique_lock lck(_qDatasMtx);
for(;;) {
  cv.wait(lck,[&]{ return _qDatas.size()>0; });
  delete _qDatas.front();
  _qDatas.pop();
}

它可以减少虚假的解锁/重新锁定。

答案 1 :(得分:3)

  

在每个帖子中调用mutex时是否需要cv.notify_one()锁定?

没有

  

std::condition_variable线程安全吗?

调用wait时,您会传递一个锁定的mutex,该锁定会立即解锁以供使用。在致电notify时,您不会使用相同的mutex锁定它,因为会发生什么(详情请参阅链接):

  1. 通知
  2. 正在等待的唤醒线程
  3. 锁定互斥锁以供使用
  4. 来自std::condition_variable

      

    在std :: condition_variable上执行notify_one或notify_all(不需要保持锁定以进行通知)

    std::condition_variable::notify_all

      

    通知线程不需要将锁定保持在与等待线程所持有的互斥锁相同的互斥锁上;

    关于您的代码段:

    //std::lock_guard<std::mutex> lck(cvMtx); //need lock here?
    cv.notify_one();
    

    不,你不需要锁定。