写在前面:
这一篇博客将讨论信号量(Semaphores)机制。将学习三种基本类型的信号量,然后将用信号量实现互斥与前趋两种进程关系。
该机制由荷兰学者 Dijkstra 提出,是一种卓有成效的进程同步工具。
在系统中,给予每一个进程一个信号量,代表每个进程目前的状态,未得到控制权的进程会在特定地方被强迫停下来,等待可以继续进行的信号到来。如果信号量是一个任意的整数,通常被称为计数信号量(Counting semaphore),或一般信号量(general semaphore);如果信号量只有二进制的0或1,称为二进制信号量(binary semaphore)。在linux系统中,二进制信号量(binary semaphore)又称互斥锁(Mutex)。——Wikipedia。
整型信号量:
最初由 Dijkstra 把整型信号量定义为一个用于表示资源数目的整型量 S,它与一般整型量不同,除初始化外,仅能通过两个标准的原子操作(Atomic Operation) wait(S)和 signal(S)来访问。这两个操作一直被分别称为 P、V 操作。wait操作是使进程等待,申请资源;signal操作是使资源释放。
其实就是利用整型数这样的一个数据结构来表示进程资源是否可用:
- 当S<=0时,资源不可用;
- 当S>0时,资源可用。
进一步,Wait(S)与Signal(S)操作可描述为:
wait(S): while S<=0 do no-op;
S:=S-1;
signal(S): S:=S+1;
wait(S)和 signal(S)是两个原子操作,因此,它们在执行时是不可中断的。亦即,当一个进程在修改某信号量时,没有其他进程可同时对该信号量进行修改。此外,在 wait 操作中,对 S 值的测试和做 S:=S-1 操作时都不可中断。
在整型信号量机制中的 wait 操作,只要是信号量 S≤0,就会不断地测试。因此,该机制并未遵循“让权等待”的准则,而是使进程处于“忙等”的状态。换句话说,一旦一个进程需要的资源不可用,那么进程就会一直等待,直到资源可用为止,相当于在火车上,想上厕所,但厕所现在有人,那么就会一直等到里面的人出来,然后去上厕所才行。而应该退出临界区。为了解决这一问题,提出了记录型信号量。
记录型信号量:
记录型信号量机制是一种不存在“忙等”现象的进程同步机制。但在采取了“让权等待”的策略后,又会出
现多个进程等待访问同一临界资源的情况。为此,在信号量机制中,除了需要一个用于代表资源数目的整型变量 value 外,还应增加一个进程链表指针 L,用于链接上述的所有等待进程。记录型信号量是由于它采用了记录型的数据结构而得名的。它所包含的上述两个数据项可描述为:
type semaphore=record
value: integer;
L: list of process;
end
相应地,wait(S)和 signal(S)操作可描述为:
procedure wait(S)
var <