Answers:
虚假唤醒的TL; DR假设(“合同”)是明智的体系结构决策,旨在允许对线程sheduler进行切实可行的实现。
“性能注意事项”在这里是无关紧要的,这些只是误解,由于在公开的权威参考文献中进行了说明而变得很普遍。(您知道吗,权威参考文献可能有误-只需问Galileo Galilei即可)。Wikipedia文章保留了对您引用的注释的引用,只是因为该注释与引用正式参考的正式指南完全吻合。
SO在此答案中提供了引入虚假唤醒概念的更多令人信服的理由,该理由基于该文章(旧版本)中提供的其他详细信息:
维基百科上有关虚假唤醒的文章有以下提示:
pthread_cond_wait()
Linux中的功能是使用futex
系统调用实现的。EINTR
当进程接收到信号时,Linux上的每个阻塞系统调用都会突然返回。...pthread_cond_wait()
无法重新开始等待,因为它可能会在futex
系统调用之外的短时间内错过一次真正的唤醒...
试想一下……就像任何代码一样,线程调度程序可能会由于基础硬件/软件中发生的异常而经历暂时的中断。当然,应尽量避免这种情况的发生,但是由于没有100%健壮的软件之类的东西,因此可以合理地假设这种情况可能发生,并在调度程序检测到这种情况时谨慎地进行恢复(例如通过观察丢失的心跳)。
现在,考虑到在停电期间它可能会丢失一些旨在通知等待线程的信号,调度程序如何恢复?如果调度程序不执行任何操作,则提到的“不幸”线程将永远挂起,一直等待-为避免这种情况,调度程序将向所有等待的线程发送信号。
这使得必须建立一个“契约”,以便可以毫无理由地通知等待线程。确切地说,这是有原因的-调度程序中断-但由于线程(出于充分的理由)被设计为不了解调度程序内部实现的详细信息,因此,此原因可能更好地表现为“虚假的”。
从线程的角度来看,这有点类似于Postel定律(也称为稳健性原理),
对自己的工作要保守,对别人接受的事情要开放
虚假唤醒的假设迫使线程在其操作上保持保守:在通知其他线程时设置条件,而在接受的条件上保持宽松:从等待返回时检查条件,如果尚未返回则重复等待。