简体   繁体   English

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

[英]Condition Variable - Wait/Notify Race Condition

I'll present some code first since explaining is easier that way. 我将首先介绍一些代码,因为解释更容易。 Assume that mutexes are correctly used with the condition variables to keep it simple: 假设互斥锁正确地与条件变量一起使用以保持简单:

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

What I would like to achieve is that thread 1 is guaranteed to be waiting on the condition variable when thread 2 or Thread 3 notifies. 我想要实现的是线程1保证在线程2或线程3通知时等待条件变量。 As the code stands, there is a large gap between notify_one() and wait() in the form of some other code marked by the comments. 正如代码所代表的那样, notify_one()wait()之间存在很大的差距,其形式是由注释标记的其他代码。 This gap means sometimes notify_one() is called before gets a chance to call wait() . 这个差距意味着有时在调用wait()之前调用notify_one() wait()

After some thought it seems that the closest I can get to this is to use some form of mutual exclusion before notify_one() and before wait() (at the start of thread 1's loop). 经过一番思考后,似乎最接近我的是在notify_one()之前和wait()之前(在线程1的循环开始时wait()使用某种形式的互斥。 However, no matter how this is done, there is still a small gap (1 line of code) between the mutual exclusion and the wait() , allowing Threads 2 and 3 to call notify_one() just before Thread 1 calls wait() . 但是,无论如何完成,在互斥和wait()之间仍然存在一个小的间隙(1行代码wait() ,允许线程2和3在线程1调用wait()之前调用notify_one() wait() It's unlikely, but possible. 这不太可能,但可能。

I also thought about using the wait() predicate to flag a boolean allowing the other threads to notify. 我还考虑过使用wait()谓词来标记一个允许其他线程通知的布尔值。 I guess this would work since wait() is atomic, but I'm wondering if there is a better way. 我想这可行,因为wait()是原子的,但我想知道是否有更好的方法。 Perhaps I am approaching this incorrectly. 也许我接近这个错误。

In summary: how can I ensure thread 1 is waiting before allowing threads 2 and 3 to notify? 总结:在允许线程2和3通知之前,如何确保线程1正在等待?

In short: think about condition variables as a method to notify other threads that something has changed, not just as a signal. 简而言之:将条件变量视为一种方法,通知其他线程某些事情发生了变化,而不仅仅是作为信号。

In order to do this, the condition variable should accompany a condition (simple example: an integer is incremented) that can be handled by the receiving thread. 为了做到这一点,条件变量应该伴随一个条件(简单的例子:一个整数递增),可以由接收线程处理。

Now, to solve your problem, thread 1 can use a condition variable accompanied by a ready boolean to signal the other threads when it is ready to receive the condition variable signal, but you better check first whether the original condition variable can be used as described here. 现在,为了解决您的问题,线程1可以使用带有ready布尔值的条件变量来在其准备接收条件变量信号时发信号通知其他线程,但是您最好先检查原始条件变量是否可以按照描述使用这里。

pseudo code based on question (proper locking of conditionVariable still needed): 基于问题的伪代码(仍然需要正确锁定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();
}

see also my previous answer 另见我之前的回答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM