我将首先介绍一些代码,因为解释更容易。假设互斥锁正确地与条件变量一起使用以保持简单:
// 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正在等待?
答案 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();
}