【问题标题】:How do three semaphores work in a synchronised execution of three threads?三个信号量如何在三个线程的同步执行中工作?
【发布时间】:2014-01-08 18:21:29
【问题描述】:
在某个系统中,三个线程的执行是使用三个信号量S1、S2和S3同步的,如下图所示。信号量 S1 和 S2 被初始化为零,而信号量 S3 被初始化为 1。所有三个信号量仅在下面显示的代码部分中使用。
Thread A Thread B Thread C
... ... ...
P(S1) P(S2) P(S3)
P(S1) P(S1) V(S1)
x=3*x+4 x=x+7 x=x*5
V(S2) V(S2) V(S1)
V(S1) V(S1) V(S3)
... ... ...
如果变量x定义为整数共享变量,初始化为1,
并且没有在代码的任何其他部分中分配值,除了
上面显示的那些,当所有线程都有时,它的值是多少
执行完毕?三个信号量的值是多少?
我正在尝试解决这篇过去的论文,以便为我的操作系统考试做准备。我不明白如何修改变量 x 以及三个信号量如何协同工作。如果有人可以逐步向我展示信号量如何协同工作以及如何修改变量,我将不胜感激。
如果您有任何其他类似的示例可以练习,请不要犹豫,将其链接起来。
【问题讨论】:
标签:
multithreading
process
thread-safety
semaphore
mutual-exclusion
【解决方案1】:
让我们来看看这个过程。
请在开始前阅读Wikipedia Article: Semaphore programming: Semantics and implementation 部分。它将解释 P() 和 V() 运算符的作用。
初始:S1=0,S2=0,S3=1
-
线程 A 递减 S1,线程 B 递减 S2。 S1=-1,S2=-1。因为这些值为负数,所以这两个线程都会阻塞。
状态:S1=-1,S2=-1,S3=0,线程 A 在 S1 上阻塞(指令 1),线程 B 在 S2 上阻塞(指令 1),线程 C 未阻塞(指令 1) , x = 1
-
线程 C 递减 S3,现在为 0。因为这不是负数,所以该线程不会阻塞。线程 C 现在递增 S1。线程 1 在 S1 上阻塞,立即解除阻塞并重新递减 S1,导致它再次阻塞。
状态:S1=-1,S2=-1,S3=0,线程 A 在 S1 上阻塞(指令 2),线程 B 在 S2 上阻塞(指令 1),线程 C 未阻塞(指令 3) , x = 1
-
线程 C 执行x=x*5,将 x 从 1 更改为 5。然后线程 C 递增 S1。线程 1,在 S1 上阻塞,立即解除阻塞。然后线程 C 再次递增 S3 并结束。
状态:S1=0,S2=-1,S3=1,线程 A 未阻塞(指令 3),线程 B 在 S2 上阻塞(指令 1),线程 C 完成,x = 5
-
线程 A 执行x=3*x+4,将 x 从 5 更改为 19。然后线程 A 递增 S2。在 S2 上阻塞的线程 B 立即解除阻塞。然后线程 A 再次增加 S1 并结束。
状态:S1=1,S2=0,S3=1,线程 A 完成,线程 B 未阻塞(指令 2),线程 C 完成,x = 19
-
线程 B 递减 S1,现在为零。因为这不是负数,所以它继续并执行x=x+7,将 x 从 19 更改为 26。线程 B 然后递增 S2,然后递增 S1 并结束。
最终状态:S1=1、S2=1、S3=1
现在让我们通过计算每个信号量的 P() 和 V() 调用来仔细检查我们的结果,并确保我们没有遗漏任何东西。由于没有循环,我们可以轻松地做到这一点,因为所有三个线程中的每条指令都只执行一次。
- S1 的初始值为 0。三个 P(S1) 调用将其递减为 -3。四个 V(S1) 调用将其增加到 1。我们的结果显示最终 S1 = 1。CHECK
- S2 的初始值为 0。一个 P(S2) 调用将该值减为 -1。两次 V(S2) 调用将其增加到 1。我们的结果显示最终 S2 = 1。CHECK
- S3 的初始值为 1。一次 P(S3) 调用将该值减为 0。一次 V(S3) 调用将该值增加为 1。我们的结果显示最终 S3 = 1。CHECK
祝你考试顺利!