条件变量 - 等待/通知竞争条件

时间:2014-01-23 09:39:47

标签: c++ multithreading thread-safety race-condition condition-variable

我将首先介绍一些代码,因为解释更容易。假设互斥锁正确地与条件变量一起使用以保持简单:

// Thread 1
while(1)
{
    conditionVariable.wait();
    // Do some work
}

// Thread 2
while(1)
{
    // Do some work
    conditionVariable.notify_one();
}

// Thread 3
while(1)
{
    // Do some work
    conditionVariable.notify_one();
}

我想要实现的是线程1保证在线程2或线程3通知时等待条件变量。正如代码所代表的那样,notify_one()wait()之间存在较大的差距,其中一些其他代码由注释标记。这个差距意味着在有机会调用notify_one()之前有时会调用wait()

经过一番思考后,似乎最接近我的是在notify_one()之前和wait()之前(在线程1的循环开始时)使用某种形式的互斥。但是,无论如何完成,互斥和wait()之间仍然存在一个小的差距(1行代码),允许线程2和3在线程1调用之前调用notify_one() wait()。这不太可能,但可能。

我还考虑使用wait()谓词来标记允许其他线程通知的布尔值。我想这可行,因为wait()是原子的,但我想知道是否有更好的方法。也许我正在接近这个。

总结:在允许线程2和3通知之前,如何确保线程1正在等待?

1 个答案:

答案 0 :(得分:4)

简而言之:将条件变量视为一种通知其他线程已发生变化的方法,而不仅仅是作为信号。

为了做到这一点,条件变量应该伴随一个条件(简单的例子:一个整数递增),可以由接收线程处理。

现在,为了解决你的问题,线程1可以使用一个条件变量,它带有一个就绪布尔值,当它准备好接收条件变量信号时发出其他线程的信号,但你最好先检查原始条件变量是否可以如此处所述使用。

基于问题的伪代码(仍然需要正确锁定conditionVariable):

// Thread 1
while(1)
{
    lockReady();
    ready = true;
    unlockReady();
    readyCV.notify_one();
    conditionVariable.wait();

    // Do some work
}

// Thread 2
while(1)
{
    lockReady();
    while (! ready) readyCV.wait();
    ready = false;
    unlockReady();
    // Do some work
    conditionVariable.notify_one();
}

// Thread 3
while(1)
{
    lockReady();
    while (! ready) readyCV.wait();
    ready = false;
    unlockReady();
    // Do some work
    conditionVariable.notify_one();
}

另见my previous answer