2017-10-19 145 views
3

我有一些像这样的代码:std :: condition_variable是线程安全的吗?

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线程安全的?

+0

为什么不'std :: queue >'? raw'new' /'delete'是C++世界中最可怕的事情之一。 – ikh

回答

2

当我在每个线程中调用cv.notify_one()时,是否需要锁定mutex

没有

std::condition_variable线程安全的?


当调用wait,你传递一个锁定mutex其立即解锁使用。当调用notify你不一样mutex锁定它,因为会发生什么的(对链接详细说明):

  1. 通知
  2. 正在等待
  3. 互斥锁使用唤醒线程

std::condition_variable

上的std :: CON执行notify_one或notify_all dition_variable(锁不需要追究通知)

std::condition_variable::notify_all

的通知线程并不需持相同的互斥由等待持有的一个锁螺纹(一个或多个);


至于你的代码片段:

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

不,你并不需要一个锁在那里。

5

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

但是,为了使正常操作正常工作并且没有通知“滑倒”的机会,您必须保持锁定条件变量在您修改虚假唤醒警戒点和/或打包条件之间读取时进行变量检查,以及通知其中的点。

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

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

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

+0

是的,你的代码比我的好。谢谢。 – francis