单个条件变量可以用于双向同步吗?

时间:2013-05-02 18:06:40

标签: c++ multithreading c++11 condition-variable

是否可以使用单个条件变量进行双向同步(即在同一个条件变量的不同时间等待两个不同的条件)?我确信在任何时候只有一个线程会在条件变量上等待。下面的示例代码说明了我在想什么:

#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();
}

2 个答案:

答案 0 :(得分:6)

是的,这是非常安全的。但是,当你真的想要通知等待条件的所有线程时,我不会养成调用notify_one的习惯,即使你“知道”只有一个线程会等待。

答案 1 :(得分:1)

从根本上说,通知条件变量实际上只声明“您正在寻找的条件可能已经发生。”

与一个条件变量进行双向通信的唯一问题是,当没有可用的数据时,线程可能会被通知唤醒。正确使用条件变量是在while循环中完成的,因此最糟糕的情况是线程看不到任何数据可用,并重新进入休眠状态。这是完全安全的,因此可以使用一个条件变量进行双向通信。

话虽如此,不必要地唤醒线程几乎没有优势,因此通常最好有一个互斥锁来保护数据(即你必须持有互斥锁以访问数据),以及两个不同的条件变量来指示不同的条件。这将最小化您唤醒线程的次数,发现它没有可处理的数据(称为“虚假”通知)。