您的位置:首页 > 职场人生

面试常考点:虚假唤醒 Spurious wakeup

2015-08-01 15:35 751 查看
https://en.wikipedia.org/wiki/Spurious_wakeup



Spurious wakeup describes a complication in the use of condition
variables as provided by certain multithreading APIs such
as POSIX Threads and the Windows
API.

Even after a condition variable appears to have been signaled from a waiting thread's point of view, the condition that was awaited may still be false. One of the reasons for this is a spurious wakeup; that is, a thread might be awoken from its waiting state
even though no thread signaled the condition variable. For correctness it is necessary, then, to verify that the condition is indeed true after the thread has finished waiting. Because spurious wakeup can happen repeatedly, this is achieved by waiting inside
a loop that terminates when the condition is true, for example:

/* In any waiting thread: */
while(!buf->full)
wait(&buf->cond, &buf->lock);

/* In any other thread: */
if(buf->n >= buf->size){
buf->full = 1;
signal(&buf->cond);
}


In this example it is known that another thread will set buf->full (the actual condition awaited) before signaling buf->cond (the means of synchronizing the two threads). The waiting thread will always verify the truth of the actual condition upon returning
from
wait
, ensuring correct behaviour if spurious wakeup occurs.

According to David R. Butenhof's Programming with POSIX Threads ISBN
0-201-63392-2:

"This means that when you wait on a condition variable, the wait may (occasionally) return when no thread specifically broadcast or signaled that condition variable. Spurious wakeups may sound
strange, but on some multiprocessor systems, making condition wakeup completely predictable might substantially slow all condition variable operations. The race
conditions that cause spurious wakeups should be considered rare."
http://siwind.iteye.com/blog/1469216
虚假唤醒(spurious wakeup)在采用条件等待时,我们使用的是

Java代码


while(条件不满足){

condition_wait(cond, mutex);

}

而不是:

If( 条件不满足 ){

Condition_wait(cond,mutex);

}

这是因为可能会存在虚假唤醒”spurious wakeup”的情况。

也就是说,即使没有线程调用condition_signal, 原先调用condition_wait的函数也可能会返回。此时线程被唤醒了,但是条件并不满足,这个时候如果不对条件进行检查而往下执行,就可能会导致后续的处理出现错误。

虚假唤醒在linux的多处理器系统中/在程序接收到信号时可能回发生。在Windows系统和JAVA虚拟机上也存在。在系统设计时应该可以避免虚假唤醒,但是这会影响条件变量的执行效率,而既然通过while循环就能避免虚假唤醒造成的错误,因此程序的逻辑就变成了while循环的情况。

注意:即使是虚假唤醒的情况,线程也是在成功锁住mutex后才能从condition_wait()中返回。即使存在多个线程被虚假唤醒,但是也只能是一个线程一个线程的顺序执行,也即:lock(mutex)  检查/处理  condition_wai()或者unlock(mutex)来解锁.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: