我已经知道你使用条件变量的方式是
lock
while not task_done
wait on condition variable
unlock
因为有时条件变量会自发唤醒。但我一直不明白为什么会这样。在过去,我读过制作一个没有这种行为的条件变量很昂贵,但仅此而已。
那么......为什么您需要担心在等待条件变量时被错误地唤醒?
我已经知道你使用条件变量的方式是
lock
while not task_done
wait on condition variable
unlock
因为有时条件变量会自发唤醒。但我一直不明白为什么会这样。在过去,我读过制作一个没有这种行为的条件变量很昂贵,但仅此而已。
那么......为什么您需要担心在等待条件变量时被错误地唤醒?
并不是条件变量会错误地唤醒;条件变量只有在从另一个线程发出信号时才会唤醒。但是,当线程被重新调度执行时,可能有其他线程已经设法获取了您正在等待的资源,因此有必要仔细检查。例如,如果一组线程 x,y,z 正在等待 w 先前持有的某个资源 R,并且 x,y,z,w 通过条件变量进行通信……假设 w 与 R 完成并发出信号 x ,y,z。因此,x、y 和 z 将全部从等待队列中取出并放入运行队列以安排执行。假设 x 首先被调度……那么它获取 R,然后它可能会进入睡眠状态,然后 y 可能会被调度,所以当 y 运行时,y 之前等待的资源 R 仍然不可用,因此 y 有必要再次进入睡眠状态。然后z醒来,z也发现R还在使用,所以z需要再回去睡觉,以此类推。
如果您恰好有两个线程,并且条件变量仅在它们两个之间共享,则有时可以不执行该检查。但是,如果您想让您的应用程序动态化并且能够扩展到任意数量的线程,那么最好养成进行额外检查的习惯(更不用说更简单和更少担心),因为它需要大多数情况。
线程可以在没有收到信号的情况下唤醒。这称为虚假唤醒。然而,正是它们为什么会发生是一个似乎陷入迷信和不确定性的问题。我看到的原因包括线程实现工作方式的副作用,或者被故意添加以强制程序员正确使用循环而不是wait
.