一、死锁的概念
1.1 死锁的定义
死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
1.2 死锁产生的原因
1、系统资源的争夺
通常系统中拥有的不可剥夺资源,其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局。只有对不可剥夺资源的竞争才可能产生死锁,对可剥夺资源的竞争是不会引起死锁的。
2、进程推进顺序非法
进程在运行过程中,请求和释放资源的顺序不当,也同样会导致死锁。例如,并发进程
P1
、
P2
分别保持资源
R1
、
R2
,而进程
P1
申请资源
R2
,进程
P2
申请资源
R1
时,两者都会因为需要资源被占用而阻塞。
信号量使用不当也会造成死锁。进程间彼此相互等待对方发来的消息,结果也会使得这些进程间无法继续向前推进。例如,进程
A
等待进程
3、死锁产生的条件
产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生。
(1)互斥条件:进程要求对所分配的资源进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
(2)不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。
(3)请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
(4)循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。即存在一个处于等待状态的进程集合{
P1,P2,...,Pn
},其中
Pi
等待的资源被
Pi+1
占有,
Pn
等待的资源被
P0
占有。
二、死锁的处理策略
1、预防死锁
设置某些限制条件,破坏产生死锁的四个必要条件中的一个或几个,以防止发生死锁。
2、避免死锁
在资源的动态分配过程中,用某种方法预防系统进入不安全状态,从而避免死锁。
3、死锁的检测及解除
无需采取任何限制性措施,允许进程在运行过程中发生死锁。通过系统的检测机构及时地检测出死锁的产生,然后采取某种措施解除死锁。
三、死锁预防
1、破坏互斥条件
如果允许系统资源都能共享使用,则系统不会进入死锁状态。但有些资源根本不能同时访问,所以,破坏互斥条件而预防死锁的方法不太可行,而且在有些时候应该保护这种互斥性。
2、破坏不可剥夺条件
当一个已保持了某些不可剥夺资源的过程,请求新的资源而得不到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。这意味着,一个进程已占有的资源会被暂时释放,或者说是被剥夺了,或从而破坏了不可剥夺条件。
3、破坏请求和保持条件
采用预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行,一旦投入运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就额可以保证系统不会发生死锁。
4、破坏循环等待条件
为了破坏循环等待条件,可采用顺序资源分配法。首先给系统中的资源编号,规定每个进程,必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源
Ri
,则该进程在以后的资源申请中,只能申请编号大于
Ri
的资源。
四、死锁避免
4.1 系统安全状态
避免死锁的方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,让进程等待。
安全状态:系统能按照某种进程推进顺序{ P1,P2,...,Pn },为每个进程 Pi 分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺序地完成。此时称{ P1,P2,...,Pn }为安全序列。
4.2 银行家算法
银行家算法是最著名的死锁避免算法。它提出的思想是:把操作系统看做是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。操作系统安装银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过该进程对资源的最大需求量,若超过则拒绝分配资源,若没有超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若能满足则按当前的申请量分配资源,否则也要推迟分配。
1、数据结构描述:
(1)可利用资源矢量(Available)
含有
m
个元素的数组,其中的每一个元素代表一类可用的资源数目。
(2)最大需求矩阵(Max)
为
(3)分配矩阵(Allocation)
为
(4)需求矩阵(Need)
为
上述三个矩阵间存在下列关系
一般情况下,在银行家算法的题目中, Max 和 Allocation 矩阵式已知条件,而求 Need 矩阵式解题的第一步。
2、算法描述
设
Requesti
是进程
Pi
的请求矢量,如果
Requesti[j]=K
,表示进程
Pi
需要
j
类资源
(1)如果
Requesti[j]≤Need[i,j]
,便转向步骤(2),否则认为出错,因为它所需要的资源数已经超过它所宣布的最大值。
(2)如果
Requesti[j]≤Available[j]
,便转向步骤(3);否则表示无足够资源,
Pi
必须等待。
(3)系统试探着把资源分配给进程
Pi
,并修改下面数据结构中的数值:
Available=Available−Requesti
Allocation[i,j]=Allocation[i.j]+Requesti[j]
Need[i,j]=Need[i,j]−Requesti[j]
(4)系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程
Pi
,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程
Pi
等待。
3、安全性算法
(1)初始安全序列为空。
(2)从
Need
矩阵中找出符合下面条件的行:该行对应的进程不在安全序列中而且该行小于
Avaliable
向量,找到后,把对应的进程加入安全序列中,如果找不到,执行步骤(4);
(3)当进程
Pi
进入安全序列后,可顺序执行,直至完成,并释放分配给它的资源,故应执行:
Avaliable=Available+Allocation[i]
,其中
Allocation[i]
表示进程
Pi
代表的在
Allocation
矩阵中对应的行,返回步骤(2)。
(4)如果此时安全序列中已经有所有的进程,则系统处于安全状态,否则,系统处于不安全状态。