条件变量可用于向其他线程发出发生了某些事情的信号:

mutex m;
condition_variable cv;

thread t1([&cv]{
    // processing
    ...
    cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck);

但是正如您所看到的,在我们等待通知之前,线程处理完成并且通知正在传递有一个机会窗口,因此我们将永远等待。

在这种情况下,一个常见的解决方案是使用标志:
mutex m;
condition_variable cv;
bool done = false;

thread t1([&cv,&done]{
    // processing
    ...
    done = true;
    cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck, [&done]{return done;});

使用标志是使用 condition_variable 的常用方法,还是我的解释错误?

最佳答案

条件变量应始终与某些条件相关联,您应该测试该条件:

unique_lock lck(m);
而(!东西)
cv.wait(lck);

保持互斥量时检查条件,这意味着互斥量应该保护与条件相关的数据,因此您知道它不会在测试和等待之间改变。

测试是一个 while 而不仅仅是一个 if 因为一些条件变量实现(包括基于 pthreads 的实现)可能会虚假地唤醒,即当没有人发出信号时,所以你应该在循环中检查条件并在它不为真时重新等待. wait 有一个重载,它接受一个谓词并通过等待谓词返回 true 来自动处理虚假唤醒,例如这是上面的示例修改为使用检查条件的 lambda:

unique_lock lck(m);
cv.wait(lck, [&] { return something; });

(在简单的情况下,我发现显式的 while 循环更容易阅读。)

一个正在使用的条件变量可以被认为是一个由条件变量、互斥体和谓词组成的三元组,它们在概念上通过一起使用来等待条件变量而绑定(bind)在一起。对特定条件变量对象的所有并发等待必须使用相同的互斥锁,并且通常也将等待相同的谓词(或依赖相同数据的相关谓词,受相同互斥锁保护。)

关于c++ - condition_variable 的常见用例场景,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10922728/

10-09 03:51