是的,您在滥用条件变量。“条件变量”实际上只是信号机制。您还需要测试一个条件。在您的情况下,可能发生的是调用notify_one()
的线程实际上在调用的线程wait()
甚至开始之前完成。(或者至少,notify_one()
呼叫发生在wait()
呼叫之前。)这称为“错过的唤醒”。
解决方案是实际上有一个包含您关心的条件的变量:
bool worker_is_done=false;
boost::mutex::scoped_lock lock(m_mutex);
while (!worker_is_done) m_condition.wait(lock);
和
boost::mutex::scoped_lock lock(m_mutex);
worker_is_done = true;
m_condition.notify_one();
如果worker_is_done==true
在另一个线程甚至开始等待之前,那么您将直接通过 while 循环而无需调用wait()
.
这种模式非常普遍,以至于我几乎可以说如果你没有一个while
循环来包裹你的condition_variable.wait()
,那么你总是有一个错误。事实上,当 C++11 采用类似于 boost::condtion_variable 的东西时,他们添加了一种新的 wait() ,它接受一个谓词 lambda 表达式(本质上它while
为你做了循环):
std::condition_variable cv;
std::mutex m;
bool worker_is_done=false;
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return worker_is_done;});