一、信号量
百度百科:信号量(Semaphore)是在多线程环境下使用的一种设施,是可用来保证两个或者多个关键代码不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦关键代码段完成了, 该线程必须要释放信号量。
二、信号量机制
1、整型信号量机制
它的值只能通过两个特定的原子操作wait和signal来改变,经典的PV操作。
var S interger;
wait(S)//申请资源
{
while S <= 0 do no - op
S = S - 1;
}
signal(S)//释放资源
{
S = S + 1;
}
2、纪录型信号量
在整形信号量机制中的wait操作,只要是信号量S≤0,就会不断测试。该机制并未遵守“让权等待”的准则,而是使进程处于“忙等”的状态。
在记录型信号量是一种不存在“忙等”现象的进程同步机制。但是采取了“让权等待”的策略后又会出现多个进程等待访问同一临界资源的情况。为此,在信号量机制中出了一个需要用于表示资源数目的整形变量value外,还应增加一个进程链表指针L,用于链接上述所有等待进程。
type semapthere = record // 信号量类型 记录型
value:integer; // 资源数目
L:list of process // 进程链表指针
end
//P、V操作如下:
procedure wait(S)
var S:semapthere; // 声明一个记录型信号量 包含value和L
begin
S.value:=S.value-1 // 申请一个资源,资源数目少一个
if S.value<0 then block(S.L); // 如果资源数目小于0,说明该类资源分配完毕,调用block原语,进行自我阻塞,放弃处理机。然后将当前进程插入到信号量链表中,此时S.value的绝对值表示该信号量链表中阻塞进程的数目。
end
procedure signal(S)
var S:semapthere;
begin
S.value:=S.value+1; // 释放一个单位资源,资源数目加1
if S.value<=0 then wakeup(S.L); // 如果资源数目小于0(加1后),表示仍然有进程处于阻塞状态,调用wakeup原语将S.L中第一个等待的进程唤醒。
end
3、AND型信号量
基本思想:将进程在整个运行过程中所需要的所有资源一次性地全部分配给进程,待进程使用完后再一起释放。只要还有一个资源不能分配给该进程,其他所有可能为之分配的资源也不能分配给它。即:对若干个临界资源的分配采取原子操作方式,要么把它所请求的资源全部分配给进程,要么一个也不分配。避免死锁的发生。
Swait(S1,S2,...,Sn)
if Si>=1 and ... and Sn>=1 then
for i:=1 to n do
Si:=Si-1;
endfor
else
//把进程插入Si阻塞队列中,并把程序计数器的值赋值为Swait的起始地址
Ssignal(S1,S2,...,Sn)
for i:=1 to n do
Si = Si+1;
//将阻塞在Si队列中的进程唤醒,插入就绪队列
endfor;