4

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

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

2 回答 2

6

Yes, it's perfectly safe. However, I wouldn't get into the habit of calling notify_one when you actually want to notify all threads waiting for the condition, even if you "know" only one thread will be waiting.

于 2013-05-02T18:12:22.807 回答
1

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

与一个条件变量进行双向通信的唯一问题是,当没有可用数据时,线程可能会被通知唤醒。条件变量的正确使用是在一个while循环中完成的,所以最坏的情况是线程发现没有可用的数据,然后重新进入睡眠状态。这是完全安全的,因此可以使用一个条件变量进行双向通信。

话虽如此,不必要地唤醒线程没有什么好处,所以通常最好有一个互斥锁来保护数据(即您必须持有互斥锁才能访问数据),以及两个不同的条件变量指示不同的条件。这将最大限度地减少您唤醒线程以发现它没有数据可处理的次数(称为“虚假”通知)。

于 2013-09-02T06:08:56.327 回答