1.信号量:
信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。信号量S的初值为0或1或其他整数,它应在系统初始化时确定。
2.PV操作:
P(S):将信号量S减1,若结果小于0,则把调用P(S)的进程置成等待信号量S的状态。
Procedure P (Var S:semaphore);
Begin
S:=S-1;
if S<0 then W(S)
End ;
V(S):将信号量S加1,若结果不大于0,则释放一个等待信号量S的进程。
Procedure V (Var S:Semaphore);
Begin
S:=S+1;
if S<=0 then R(S)
end ;
3.进程的互斥
PV操作时解决进程的互斥的有效工具。比如:当只有一张机票时,有两个旅客同时购买,会引发与时间有关的错误。采用pv操作可以解决这个问题。
Process Pi
Begin
…
P(S);
临界区I;
V(S);
…
End
使用PV操作实现进程互斥时应该注意的是:
1.每个程序中用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。若有多个分支,要认真检查其成对性。
2.P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。
3.互斥信号量的初值一般为1。
理解:
当一个进程在临界区执行时被中断,但它在临界区的操作并没有完成,因而不会去调用V(S)。假设当一个进程A在临界区执行时被中断后,另一个进程B占用了处理器,如果进程B也要进入临界区,则一定要先调用P(S),但此时被中断的进程A尚未退出临界区,S的值仍为0,所以想进入临界区的进程B调用P(S)的结果必然是等待。只有当被中断的进程A再次占用处理器,完成了临界区的操作后,调用了V(S)才允许其他进程进入临界区。
4.进程的同步
举个例子:
假定缓冲器的容量为每次只能存放一个记录。进程A把一个记录送入缓冲器后,应等到进程B发来消息(已将缓冲器中的记录取走)才能把下一个记录送入缓冲器。进程B把已存入缓冲器的记录取走后,也应该等到进程A发来消息(缓冲器中已存入一个待加工的记录),才能从缓冲器中取出记录去加工。
如果两个进程不互相制约的话,就会出现错误。 进程A把一个记录存入缓冲器后,进程B还没有取走该记录,而进程A又把新读来的记录存入缓冲器,这样就把上一个没有取走的记录覆盖了。同样,如果进程B在下一个记录存入缓冲器之前,又去取缓冲器中的记录,则造成重复去同一个记录。这种错误的出现是由两个进程的执行速度造成的。所以AB之间必须同步。
使用PV操作实现进程同步时应该注意的是:
1.分析进程间的制约关系,确定信号量种类。在保持进程间有正确的同步关系情况下,哪个进程先执行,哪些进程后执行,彼此间通过什么资源(信号量)进行协调,从而明确要设置哪些信号量。
2.信号量的初值与相应资源的数量有关,也与P、V操作在程序代码中出现的位置有关。
3.同一信号量的P、V操作要成对出现,但它们分别在不同的进程代码中。