我一直在读"信号量小书",在第41页有一个可重用屏障问题的解决方案。我遇到的问题是为什么它不会产生死锁情况。
1 # rendezvous
2
3 mutex.wait()
4 count += 1
5 if count == n:
6 turnstile2.wait() # lock the second
7 turnstile.signal() # unlock the first
8 mutex.signal()
9
10 turnstile.wait() # first turnstile
11 turnstile.signal()
12
13 # critical point
14
15 mutex.wait()
16 count -= 1
17 if count == 0:
18 turnstile.wait() # lock the first
19 turnstile2.signal() # unlock the second
20 mutex.signal()
21
22 turnstile2.wait() # second turnstile
23 turnstile2.signal()
在这个解决方案中,在第 15 行和第 20 行之间,在信号量(第 18 行)上调用 wait() 同时持有导致死锁的互斥锁,这不是一个坏习惯吗?请解释一下。谢谢。
mutex
保护count
变量。 第一个互斥锁涉及递增计数器以考虑每个线程,最后一个进入的线程(if count == n
)锁定第二个tunstile以准备离开(见下文)并释放等待的(n-1)线程(在第10行等待)。 然后每个信号都向下一个发出信号。
第二个互斥锁的工作方式与第一个类似,但递减count
(相同的多文保护它)。 进入互斥块的最后一个线程锁定turnstile
为下一个批处理条目做准备(见上文),并释放在第 22 行等待的 (n-1) 线程。 然后每个线程都向下一个线程发出信号。
因此turnstile
协调入口到临界点,而turnstile2
协调从该点的出口。
不可能有死锁:当(最后一个)线程到达第 18 行时,turnstile
保证不会被任何其他线程持有(它们都在第 22 行等待)。 与turnstile2
类似