Skip to content

Commit 719ab57

Browse files
committed
update ch8-4
1 parent ef0086d commit 719ab57

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

source/chapter8/4condition-variable.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@
354354
355355
第 31 和 32 行我们分别创建要用到的条件变量和互斥锁。在 ``second`` 中,首先有一层互斥锁保护,然后由于条件变量是 Mesa 语义的,所以我们需要使用 while 循环进行等待,不符合条件调用 ``condvar_wait`` 阻塞自身的时候还要给出当前持有的互斥锁的 ID ;在 ``first`` 中,最外层同样有互斥锁保护。在修改完成之后只需调用 ``condvar_signal`` 即可唤醒执行 ``second`` 的线程。
356356

357-
**在使用条件变量的时候需要特别注意** :ref:`唤醒丢失 <term-lost-wakeup>` **问题** 。也就是说和信号量不同,如果调用 ``signal`` 的时候没有任何线程在条件变量的阻塞队列中,那么这次 ``signal`` 不会有任何效果,这次唤醒也不会被记录下来。
357+
**在使用条件变量的时候需要特别注意** :ref:`唤醒丢失 <term-lost-wakeup>` **问题** 。也就是说和信号量不同,如果调用 ``signal`` 的时候没有任何线程在条件变量的阻塞队列中,那么这次 ``signal`` 不会有任何效果,这次唤醒也不会被记录下来。对于这个例子来说,我们在 ``first`` 中还会修改 ``A`` ,因此如果 ``first`` 先执行,即使其中的 ``signal`` 没有任何效果,之后执行 ``second`` 的时候也会发现条件已经满足而不必进入阻塞。
358358

359359
.. 有了上面的介绍,我们就可以实现条件变量的基本逻辑了。下面是条件变量的wait和signal操作的伪代码:
360360
@@ -392,7 +392,7 @@
392392
exit(0)
393393
}
394394
395-
可以将 ``thread_fn`` 分成打印字符 a、打印字符 b 和打印字符 c 这三个阶段。考虑这样一种同步需求:即在阶段间设置 **同步屏障** ,只有 *所有的* 线程都完成上一阶段之后,这些线程才能够进入下一阶段。也就是说,如果有线程更早完成了一个阶段,那么它需要等待其他较慢的线程也完成这一阶段才能进入下一阶段。最后的执行结果应该是所有的 a 被打印出来,然后是所有的 b ,最后是所有的 c 。同学们在向下阅读之前可以思考如何用我们学过的同步原语来实现这种同步需求呢?
395+
可以将 ``thread_fn`` 分成打印字符 a、打印字符 b 和打印字符 c 这三个阶段。考虑这样一种同步需求:即在阶段间设置 **同步屏障** ,只有 *所有的* 线程都完成上一阶段之后,这些线程才能够进入下一阶段。也就是说,如果有线程更早完成了一个阶段,那么它需要等待其他较慢的线程也完成这一阶段才能进入下一阶段。最后的执行结果应该是所有的 a 被打印出来,然后是所有的 b ,最后是所有的 c 。同学们在向下阅读之前可以思考如何用我们学过的同步原语来实现这种同步需求。
396396

397397
这里给出基于互斥锁和条件变量的一种参考实现:
398398

0 commit comments

Comments
 (0)