我对线程被唤醒和锁不可用有一点怀疑
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。
我的问题是,如果另一个线程醒来并发现相关的互斥锁仍然不可用,它会再次休眠。这不是错过信号的条件吗?
答案 0 :(得分:5)
如果另一个线程醒来并发现相关的互斥锁仍然不可用,它会再次休眠
重新获取互斥锁后,它会继续测试该条件。
条件变量通知实质上是条件可能已更改并需要重新评估的提示。可以有spurious wake-ups。代码等待条件变为真,而不是信号。
答案 1 :(得分:4)
&#34;睡眠&#34>之间存在差异。在条件变量(即等待信号)和&#34;睡眠&#34;在互斥锁上(即等待锁定它)。
如果线程从等待条件变量唤醒并且互斥锁仍然被锁定,则它开始等待互斥锁,直到它可以获取它,然后检查条件(即谓词)。这与再次等待condvar不一样,所以没有遗漏任何东西。它还在等待检查条件是否为真,在获取互斥锁之前它无法执行。
假设您在醒来时正确检查了条件(这是您传递给condition_variable::wait
的谓词),那么您将不会错过导致信号的事件。