是否可以使用单个条件变量进行双向同步(即在同一个条件变量的不同时间等待两个不同的条件)?我确信在任何时候只有一个线程会在条件变量上等待。下面的示例代码说明了我在想什么:
#include <condition_variable>
#include <thread>
#include <mutex>
#include <iostream>
std::condition_variable condvar;
std::mutex mutex;
int i;
void even()
{
while (i < 10000) {
std::unique_lock<std::mutex> lock(mutex);
if (i % 2 != 0) {
condvar.notify_one();
condvar.wait(lock, [&](){ return i % 2 == 0; });
}
i++;
std::cout << i << std::endl;
}
condvar.notify_one();
}
void odd()
{
while (i < 10001) {
std::unique_lock<std::mutex> lock(mutex);
if (i % 2 != 1) {
condvar.notify_one();
condvar.wait(lock, [&](){ return i % 2 == 1; });
}
i++;
std::cout << i << std::endl;
}
}
int main()
{
i = 0;
std::thread a(even);
std::thread b(odd);
a.join();
b.join();
}
答案 0 :(得分:6)
是的,这是非常安全的。但是,当你真的想要通知等待条件的所有线程时,我不会养成调用notify_one
的习惯,即使你“知道”只有一个线程会等待。
答案 1 :(得分:1)
从根本上说,通知条件变量实际上只声明“您正在寻找的条件可能已经发生。”
与一个条件变量进行双向通信的唯一问题是,当没有可用的数据时,线程可能会被通知唤醒。正确使用条件变量是在while循环中完成的,因此最糟糕的情况是线程看不到任何数据可用,并重新进入休眠状态。这是完全安全的,因此可以使用一个条件变量进行双向通信。
话虽如此,不必要地唤醒线程几乎没有优势,因此通常最好有一个互斥锁来保护数据(即你必须持有互斥锁以访问数据),以及两个不同的条件变量来指示不同的条件。这将最小化您唤醒线程的次数,发现它没有可处理的数据(称为“虚假”通知)。