引用手册页:
使用条件变量时,总会有一个布尔谓词,涉及与每个条件等待关联的共享变量,如果线程应该继续,则为真.可能会发生pthread_cond_timedwait()或pthread_cond_wait()函数的虚假唤醒.由于从pthread_cond_timedwait()或pthread_cond_wait()返回并不意味着有关此谓词的值的任何内容,因此应在返回时重新评估谓词.
因此,pthread_cond_wait即使您没有发信号也可以返回.乍一看,这看起来非常残酷.它就像一个随机返回错误值或在实际到达正确的返回语句之前随机返回的函数.这似乎是一个主要的错误.但是他们选择在手册页中记录这一点而不是修复它的事实似乎表明有一个合理的理由为什么pthread_cond_wait最终虚假地唤醒.据推测,它有一些内在的关于它是如何工作的,这使它无法帮助.问题是什么.
为什么没有pthread_cond_wait虚假回报?为什么它不能保证它只是在它被正确发出信号后醒来?谁能解释其虚假行为的原因?
acm*_*acm 98
至少有两件事"虚假唤醒"可能意味着:
pthread_cond_wait可以从呼叫返回,即使在条件发生时没有呼叫信号或广播.pthread_call_signal由于调用信号或广播而阻塞返回的线程,但是在重新获取互斥锁之后,发现基础谓词不再为真.但即使条件变量实现不允许前一种情况,也可能发生后一种情况.考虑生产者消费者队列和三个线程.
pthread_cond_broadcast在等待信号/广播的呼叫中的互斥,呼叫和块下检查时,发现队列为空.因此,您始终需要在循环下检查谓词,如果基础条件变量可以具有其他类型的虚假唤醒,则没有区别.
NPE*_*NPE 75
David R. Butenhof在"使用POSIX线程编程"(第80页)中给出了以下解释:
虚假唤醒可能听起来很奇怪,但在某些多处理器系统上,使条件唤醒完全可预测可能会大大减慢所有条件变量操作.
在下面的comp.programming.threads讨论中,他扩展了设计背后的思路:
Patrick Doyle wrote: > In article , Tom Payne wrote: > >Kaz Kylheku wrote: > >: It is so because implementations can sometimes not avoid inserting > >: these spurious wakeups; it might be costly to prevent them. > >But why? Why is this so difficult? For example, are we talking about > >situations where a wait times out just as a signal arrives? > You know, I wonder if the designers of pthreads used logic like this: > users of condition variables have to check the condition on exit anyway, > so we will not be placing any additional burden on them if we allow > spurious wakeups; and since it is conceivable that allowing spurious > wakeups could make an implementation faster, it can only help if we > allow them. > They may not have had any particular implementation in mind. You're actually not far off at all, except you didn't push it far enough. The intent was to force correct/robust code by requiring predicate loops. This was driven by the provably correct academic contingent among the "core threadies" in the working group, though I don't think anyone really disagreed with the intent once they understood what it meant. We followed that intent with several levels of justification. The first was that "religiously" using a loop protects the application against its own imperfect coding practices. The second was that it wasn't difficult to abstractly imagine machines and implementation code that could exploit this requirement to improve the performance of average condition wait operations through optimizing the synchronization mechanisms. /------------------[ David.Buten...@compaq.com ]------------------\ | Compaq Computer Corporation POSIX Thread Architect | | My book: http://www.awl.com/cseng/titles/0-201-63392-2/ | \-----[ http://home.earthlink.net/~anneart/family/dave.html ]-----/
pthread_cond_signal中的"条件信号的多次唤醒"部分具有pthread_cond_wait和pthread_cond_signal的示例实现,其涉及虚假唤醒.
虽然我不认为在设计时考虑过它,但这是一个实际的技术原因:结合线程取消,在某些情况下,选择“虚假”唤醒可能是绝对必要的,至少除非您愿意对可能的实施策略施加非常强的限制。
关键问题是,如果一个线程在被阻塞时执行了取消操作pthread_cond_wait,那么副作用就好像它没有消耗条件变量上的任何信号一样。然而,当您开始对取消采取行动时,很难(并且受到高度限制)确保您尚未消耗信号,并且在此阶段可能无法将信号“重新发布”到条件变量,因为您可能在这种情况下,调用者pthread_cond_signal已经有理由销毁 condvar 并释放它所在的内存。
虚假唤醒的津贴让您轻松出局。如果您可能已经消耗了一个信号(或者如果您想偷懒,无论如何),而不是在它到达时在条件变量上阻塞时继续对取消采取行动,您可以声明一个虚假的唤醒已经发生,并成功返回。这根本不会干扰取消的操作,因为正确的调用者将在下一次循环并pthread_cond_wait再次调用时对挂起的取消进行操作。
| 归档时间: |
|
| 查看次数: |
27317 次 |
| 最近记录: |