小编典典

为什么 pthread_cond_wait 有虚假唤醒?

all

引用手册页:

当使用条件变量时,总是有一个布尔谓词涉及与每个条件相关联的共享变量等待如果线程应该继续,则该条件等待为真。可能会发生来自 pthread_cond_timedwait() 或 pthread_cond_wait() 函数的虚假唤醒。由于 pthread_cond_timedwait() 或 pthread_cond_wait() 的返回并不暗示该谓词的任何值,因此应在此类返回时重新评估谓词。

因此,pthread_cond_wait即使您没有发出信号,也可以返回。至少乍一看,这似乎很残酷。这就像一个随机返回错误值或在实际到达正确的返回语句之前随机返回的函数。这似乎是一个重大错误。但是他们选择在手册页中记录这一点而不是修复它的事实似乎表明有一个合理的原因导致pthread_cond_wait最终被虚假唤醒。据推测,它的工作原理有一些内在的东西使它无法帮助。问题是什么。

为什么pthread_cond_wait虚假返回?为什么它不能保证只有在收到正确的信号时才会醒来?谁能解释其虚假行为的原因?


阅读 107

收藏
2022-03-04

共1个答案

小编典典

至少有两件事“虚假唤醒”可能意味着:

  • pthread_cond_wait即使没有对条件pthread_call_signal或条件的调用发生,阻塞的线程也可以从调用中返回pthread_cond_broadcast
  • pthread_cond_wait由于调用pthread_cond_signalor而被阻塞的线程返回pthread_cond_broadcast,但是在重新获取互斥锁后,发现底层谓词不再为真。

但是即使条件变量实现不允许前一种情况,后一种情况也可能发生。考虑一个生产者消费者队列和三个线程。

  • 线程 1 刚刚将一个元素出列并释放了互斥锁,队列现在为空。线程正在对它在某个 CPU 上获取的元素执行任何操作。
  • pthread_cond_wait线程 2 尝试使元素出列,但在等待信号/广播的调用中的互斥锁、调用和块下检查时发现队列为空。
  • 线程 3 获得互斥体,向队列中插入新元素,通知条件变量,释放锁。
  • 响应来自线程 3 的通知,正在等待条件的线程 2 被调度运行。
  • 然而,在线程 2 设法获得 CPU 并获取队列锁之前,线程 1 完成了它的当前任务,并返回队列做更多工作。它获取队列锁,检查谓词,发现队列中有工作。它继续使线程 3 插入的项目出列,释放锁,然后对线程 3 入队的项目执行任何操作。
  • 线程 2 现在在 CPU 上获取锁,但是当它检查谓词时,发现队列是空的。线程 1“偷”了该项目,因此唤醒似乎是虚假的。线程 2 需要再次等待条件。

因此,由于您已经总是需要检查循环下的谓词,因此底层条件变量是否可以具有其他类型的虚假唤醒没有区别。

2022-03-04