2017-07-27 49 views
2

对这个问题的回答是错误的,因为它有机会发生死锁。 Condition Variable - Wait/Notify Race Condition如何解决条件变量wait/notify的竞态条件

我没有找到解决竞态条件或死锁问题的解决方案。

想象一下,我们有两个线程。现在的目标如下。

first condition: 
Thread 1 Waits 
Thread 2 Notifies 

second condition: 
Thread 2 Notifies 
Thread 1 Should not wait and continue normal execution. 

如何在不通知队列的情况下正确实现这个功能?因为我希望这部分代码尽可能快地运行,并使用布尔值而不是将项目添加到队列中。也只有2个线程,所以使用队列似乎对我来说过分了。

在有竞争条件的伪代码:

Thread 1: 
lock(x); 
if(!signaled) 
{ 
    unlock(x); // ******** 
    // still small gap, how to avoid? 
    cv.wait(); // forget spurious wakeup for sake of simplicity 
    signaled = false; 
} 
else // ******** 
    unlock(x); 

Thread 2: 
lock(x); 
signaled = true; 
cv.notify(); 
unlock(x); 

现在,如果你删除与********竞争条件注释两条线都将迎刃而解和僵局的机会将被引入其中线程1等待,而拥有的锁,线程2卡在锁定x。

+0

您可能想使用['std :: atomic'](http://en.cppreference.com/w/cpp/atomic/atomic)机制来处理这个案例。 – tadman

+2

你的假设是不正确的。 'conditional_variable :: wait' **原子**进入等待模式并释放锁。 – SergeyA

+0

即使'conditional_variable :: wait'释放了锁,我很确定它在**等待之前就这么做了,所以差距仍然存在于内部@SergeyA –

回答

3

你的困惑的根源是你对条件变量的误解。它们的固有特性是锁定释放并进入等待模式,原子地完成,即在两者之间没有任何反应。

因此,在变量进入等待模式之前,不能对变量进行修改,因为锁定不会被释放。这是任何符合conditional_variable实施的基本保障,例如,这里是从参考页的提取物std::conditional_variable

http://en.cppreference.com/w/cpp/thread/condition_variable/wait

以原子释放锁,阻止当前执行的线程,和 增加它到等待* this的线程列表。当notify_all()或notify_one()被执行时,线程将被解除阻塞 。它也可能 虚假地被解除封锁。当解锁时,无论原因如何, 锁将被重新获取并等待退出。如果此功能通过 异常退出,则锁定也会重新获取。 (直到C++ 14)

+0

好,忘了我以前的评论,如果两个操作是原子完成然后问题就解决了。你能否参考你的陈述? –

+1

我会在你使用的任何API。假如你使用C++,它将在'conditional_variable :: wait'的文档中。将提出答案。 – SergeyA