C++ 条件变量的虚假唤醒(Spurious Wakeup)问题

问题

在实现线程池时,遇到一个条件变量的坑,可能在预期之外的情况下,被阻塞的线程被唤醒。
这样之前要等待的某个条件实际上并没有符合,被唤醒的线程将执行一系列非法操作。


原因

这种情况在使用条件变量时很常见,在程序收到信号时就可能发生。
可以在设计时,通过某些设定避免虚假唤醒,但是这样会影响条件变量的执行效率。


解决方案

在条件变量阻塞的代码段,增加一个while循环,如果被唤醒就要检查一下条件是否符合,
如果不符合则要再次阻塞等待。
这样即避免了忙等待,又避免了虚假唤醒问题。

1
2
3
4
5
6
lock(mutex);
while( something not true ) {  
    condition_wait( cond, mutex);
}
do(something);
unlock(mutex);