【发布时间】:2010-04-28 06:24:18
【问题描述】:
我早就知道你使用条件变量的方式是
lock
while not task_done
wait on condition variable
unlock
因为有时条件变量会自发唤醒。但我一直不明白为什么会这样。过去我读过,制作一个没有这种行为的条件变量很昂贵,但仅此而已。
那么...为什么你需要担心在等待条件变量时被错误地唤醒?
【问题讨论】:
标签: concurrency condition-variable
我早就知道你使用条件变量的方式是
lock
while not task_done
wait on condition variable
unlock
因为有时条件变量会自发唤醒。但我一直不明白为什么会这样。过去我读过,制作一个没有这种行为的条件变量很昂贵,但仅此而已。
那么...为什么你需要担心在等待条件变量时被错误地唤醒?
【问题讨论】:
标签: concurrency condition-variable
不是条件变量会错误唤醒;条件变量只有在从另一个线程发出信号时才会唤醒。但是,有可能在线程被重新调度执行时,其他线程已经设法获取了您正在等待的资源,因此有必要仔细检查。例如,如果一组线程 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 周围的条件。
【讨论】:
select 返回可读,然后没有可读取的内容。 write 将在 50% 的时间内返回部分结果。条件变量会自发唤醒。等等。