在c ++ 11条件变量中丢失信号

时间:2017-02-17 17:28:29

标签: multithreading 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。

我的问题是,如果另一个线程醒来并发现相关的互斥锁仍然不可用,它会再次休眠。这不是错过信号的条件吗?

2 个答案:

答案 0 :(得分:5)

  

如果另一个线程醒来并发现相关的互斥锁仍然不可用,它会再次休眠

重新获取互斥锁后,它会继续测试该条件。

条件变量通知实质上是条件可能已更改并需要重新评估的提示。可以有spurious wake-ups。代码等待条件变为真,而不是信号。

答案 1 :(得分:4)

&#34;睡眠&#34>之间存在差异。在条件变量(即等待信号)和&#34;睡眠&#34;在互斥锁上(即等待锁定它)。

如果线程从等待条件变量唤醒并且互斥锁仍然被锁定,则它开始等待互斥锁,直到它可以获取它,然后检查条件(即谓词)。这与再次等待condvar不一样,所以没有遗漏任何东西。它还在等待检查条件是否为真,在获取互斥锁之前它无法执行。

假设您在醒来时正确检查了条件(这是您传递给condition_variable::wait的谓词),那么您将不会错过导致信号的事件。