什么是Semaphore
从定义来看:
A semaphore can be abstractly viewed as a pair
(
v
,
L
)
(v, L)
(v,L) of a natural number
v
v
v of a natural numver
v
v
v and a set of process
L
L
L. The semaphore must always be initialised to some
(
v
,
∅
)
(v,\empty)
(v,∅).
wait(S)
or P(S)
, decrements
v
v
v if positive, otherwise adds
p
p
p to
L
L
L and blocks
p
p
p.
signal(S)
or V(S)
, if
L
≠
∅
L\ne \empty
L=∅, unblocks a member of
L
L
L. Otherwise increment
v
v
v.
可以认为Semaphore类似锁,当有钥匙时,进程可以打开进入,没有钥匙就停下等待。但是等待(implementation)的方式不同,可以分为Weak Semaphore,busy-wait semaphore以及Strong Semaphore。
使用Semaphore可以解决critical sections问题,他的正确性可以被证明(虽然看起来很复杂,有时间以后的文章会写)。
Critical Sections
对于这个问题有四个衡量标准,分别是
mutual exclusion: 至多有一个进程在他的critical section。
Eventual entry:如果一个进程想要进入他的critical section,那么他最终可以进入。
Absence of deadlock:无死锁
Absence of unnecessary delay:当只有一个process想进入它当critical section的时候,它可以直接进入。
Busy-wait Semaphore
这个算是写起来最简单,但是效果算是最不理想的一类了。
先看一个例子
inline wait(S) {d_step { S > 0; S-- }}
inline signal(S) { d_step { S++ }}
当 S S S为0的时候,就一直在一个loop里面直到 S S S不为0 。定义里的set L L L 不过是 ”the set of (busy-) waiting processes on the integer“。
Weak Semaphore
Weak Semaphore和busy-wait的区别是它的的确确用了set,因此不需要用循环来使进程停下(但是由于不同语言的写法,例如java还是需要写while)。用一个图来看(图片传不上去只能先这样):
https://i.loli.net/2020/06/27/O3JG9LudbyNAYDR.png
假设我们只有两个process,weak和busy-wait满足eventual entry
吗?
显然weak会满足,因为当p signal的时候q就可以运行了。但是busy-wait不行,当p运行了signal
之后,S的的确确大于0,但是这不意味着q会被运行。schedular可能依然会选择p。
那么如果有N个进程呢?
我们会遇到两个问题:
- 这两个都不满足
enventual entry
如果我们没有对于signal
进行公平性的假设。weak不满足因为假设有p,q和r三个,完全有可能p和q互相signal把q扔在一边。 - 但是即使我们假设了公平性,也不会满足linear waiting。
想要解决这个问题,就需要我们的strong semaphore出场了。
Strong Semaphore
它的解决办法是我们不用set了,改用Queue,所有都按FIFO操作。这个确实解决了上述问题,但是实现的难度却大了很多,效率也有可能会被影响。
– used some stuff from Ben Ari’s text book.
– Written by Tina.