2017-02-17 37 views
0

我已經被喚醒約線程一個小疑問和鎖定錯過了在C++ 11條件變量信號

std::mutex mut; 
std::queue<data_chunk> data_queue; 
std::condition_variable data_cond; 

void data_preparation_thread() {  
    while(more_data_to_prepare()) {   
     data_chunk const data=prepare_data();   
     std::lock_guard<std::mutex> lk(mut);   
     data_queue.push(data);      
     data_cond.notify_one(); //mutex is still locked here  
    } 
} 

void data_processing_thread() { 
    while(true) { 
     std::unique_lock<std::mutex> lk(mut); 
     data_cond.wait(lk,[]{return !data_queue.empty();}); //what if lk could not acquire the mutex. 
     data_chunk data=data_queue.front();   
     data_queue.pop();   
     lk.unlock(); 
     process(data); 
     if(is_last_chunk(data)) 
      break; 
    } 

}

在上面的例子data_preparation_thread()的不可用性使數據在隊列並通知和線程等待condition_variable。

我的問題是,如果另一個線程喚醒並發現關聯的互斥鎖仍然不可用,它會再次休眠。這不是錯過信號的情況嗎?

回答

4

如果其他線程被喚醒,並查找相關的互斥量仍然不可用,它再次

睡一旦它重新獲得它進行測試條件互斥。

條件變量通知本質上暗示條件可能已經發生變化,需要重新評估。可以有spurious wake-ups。代碼等待條件成真,而不是信號。

3

條件變量(即等待信號)上的「休眠」和互斥體上的「休眠」(即等待鎖定它)之間存在差異。

如果線程從等待條件變量中喚醒並且互斥鎖仍然鎖定,它將開始等待互斥鎖,直到它可以獲取它,然後檢查條件(即謂詞)。這與再次等待condvar不一樣,所以沒有錯過任何東西。它仍然在等待檢查條件是否爲真,它在獲取互斥鎖之前無法做到。

假設您在醒來時正確檢查了條件(這是您傳遞給condition_variable::wait的謂詞所做的),那麼您將不會錯過導致信號的事件。