Multithreading POSIX条件变量与Win32事件对象(关于虚假唤醒问题)

Multithreading POSIX条件变量与Win32事件对象(关于虚假唤醒问题),multithreading,pthreads,locking,condition-variable,spurious-wakeup,Multithreading,Pthreads,Locking,Condition Variable,Spurious Wakeup,在POSIX中,由于“虚假唤醒”问题,程序员在检查条件时被迫使用while()而不是if 我认为虚假唤醒是一个不直观和令人困惑的问题,但我认为这是一个不可避免的问题 最近,我发现win32的事件对象没有“虚假唤醒”问题 为什么POSIX系统和其他系统仍然使用存在“伪唤醒”问题的条件变量?(尽管这可以解决吗?你问: 为什么POSIX系统和其他系统仍然使用存在“伪唤醒”问题的条件变量?(尽管如此,还是可以解决吗?) 基本上,它比另一种更快 POSIX.1-2017处理pthread_cond_广播和

在POSIX中,由于“虚假唤醒”问题,程序员在检查条件时被迫使用
while()
而不是
if

我认为虚假唤醒是一个不直观和令人困惑的问题,但我认为这是一个不可避免的问题

最近,我发现win32的事件对象没有“虚假唤醒”问题

为什么POSIX系统和其他系统仍然使用存在“伪唤醒”问题的条件变量?(尽管这可以解决吗?

你问:

为什么POSIX系统和其他系统仍然使用存在“伪唤醒”问题的条件变量?(尽管如此,还是可以解决吗?)

基本上,它比另一种更快

POSIX.1-2017处理
pthread_cond_广播
pthread_cond_信号
的基本原理部分特别提到:

虽然[虚假唤醒]问题可以解决,很少发生的边缘条件的效率损失是不可接受的,特别是考虑到必须检查与条件变量相关联的谓词。纠正此问题将不必要地降低此基本构造块中所有高级同步操作的并发程度

重点补充

本文进一步指出,强制“围绕条件等待的谓词测试循环”是一种比替代方法更稳健的编码实践,因为应用程序必然会容忍代码中其他地方的多余广播和信号。

您会问:

为什么POSIX系统和其他系统仍然使用存在“伪唤醒”问题的条件变量?(尽管如此,还是可以解决吗?)

基本上,它比另一种更快

POSIX.1-2017处理
pthread_cond_广播
pthread_cond_信号
的基本原理部分特别提到:

虽然[虚假唤醒]问题可以解决,很少发生的边缘条件的效率损失是不可接受的,特别是考虑到必须检查与条件变量相关联的谓词。纠正此问题将不必要地降低此基本构造块中所有高级同步操作的并发程度

重点补充


本文进一步指出,强制“围绕条件等待的谓词测试循环”是一种比替代方法更健壮的编码实践,因为应用程序必然会容忍代码中其他地方的多余广播和信号。

Spurrious wakeup是对CV的等待返回,即使该CV没有发出信号。这种情况确实发生过,但非常罕见。健壮代码需要适应的一种更可能的情况是,在CV发出信号后,线程从等待中返回,但关联的谓词仍然是false(至少在线程实际返回时是false)。在各种情况下,这是完全自然的。将您的CV wait放入循环中仍然是正确的做法,不会出现虚假唤醒的可能性。我还要注意的是,它包含自己的谓词,即“有信号”或“无信号”的“状态”。您可以轻松地构造自己的
struct my_event
(带有condvar、mutex和标志)和
my_event\u timedwait(struct my_event*,struct timespec*timeout)
,它隐藏谓词测试循环,因此适合在
if
条件下使用。伪唤醒是对CV的等待返回,即使该CV没有发出信号。这种情况确实发生过,但非常罕见。健壮代码需要适应的一种更可能的情况是,在CV发出信号后,线程从等待中返回,但关联的谓词仍然是false(至少在线程实际返回时是false)。在各种情况下,这是完全自然的。将您的CV wait放入循环中仍然是正确的做法,不会出现虚假唤醒的可能性。我还要注意的是,它包含自己的谓词,即“有信号”或“无信号”的“状态”。您可以轻松地构造自己的
struct my_event
(带有condvar、mutex和标志)和
my_event\u timedwait(struct my_event*,struct timespec*timeout)
,它隐藏谓词测试循环,因此适合在
if
条件测试中使用。