2017-10-19 144 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