2017-02-17 20 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的谓词所做的),那么您将不会错过导致信号的事件。