死锁
死锁的基本概念
在多道程序系统中,并发执行的多个进程因争夺 资源而造成的一种若无外力作用有关进程都将永 远不能向前推进的僵持状态或僵局 。
死锁产生的原因
-
系统资源的竞争
通常系统中拥有的不可剥夺资源,其数量不足以满足多个进程运行的需要,使得进程在 运行过程中,会因争夺资源而陷入僵局,如磁带机、打印机等。只有对不可剥夺资源的竞争 才可能产生死锁,对可剥夺资源的竞争是不会引起死锁的
-
进程推进顺序非法
进程在运行过程中,请求和释放资源的顺序不当,也同样会导致死锁。例如,并发进程 P1、P2分别保持了资源R1、R2,而进程P1申请资源R2,进程P2申请资源R1时,两者都 会因为所需资源被占用而阻塞。
-
信号量使用不当也会造成死锁
进程间彼此相互等待对方发来的消息,结果也会使得这 些进程间无法继续向前推进。例如,进程A等待进程B发的消息,进程B又在等待进程A 发的消息,可以看出进程A和B不是因为竞争同一资源,而是在等待对方的资源导致死锁。
产生死锁的必要条件
必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生
- 互斥条件:进程对于所分配到的资源(如打印机)具有排它性,即一个资源只能被一个进程占用,直到被该进程释放 。由于互斥条件是资源本身性质决定的,不能从这一条件解决或预防死锁。
- 请求和保持条件:一个进程因请求被占用资源而发生阻塞时,对已获得的资源保持不放。
- 不剥夺条件:任何一个资源在没被该进程释放之前,任何其他进程都无法对他剥夺占用
- 循环等待条件:当发生死锁时,所等待的进程必定会形成一个环路(类似于死循环),造成永久阻塞。
处理死锁的基本方法
-
预防死锁 :设置某些限制前提以破坏产生死锁必要条件
-
避免死锁 :资源动态分配过程中,利用某种方法去防止 系统进入不安全状态
安全状态与不安全状态:安全状态指系统能按某种进程顺序来为每个进程分配其所需资源,直 至最大需求,使每个进程都可顺利完成,称使进程能够顺利完成的执行序列为安全序列 。 若系统不存在这样一个序列, 则称系统处于不安全状态。
避免死锁就是避免系统进入不安全状态!
不安全状态不意味着就是死锁,只是有可能发生死锁。有可能进程推进过程中会自己释放某些资源,使得每个进程都可顺利完成。
-
检测死锁 :运行过程中通过系统设置的检测机构及时检 测死锁的发生,并精确确定相关进程和资源
-
解除死锁 :撤销或挂起一些进程以回收资源和再分配
死锁的预防策略
- 摒弃“请求和保持”条件
- 办法:系统要求所有进程在开始运行之前,都必须 一次性地申请其在整个运行过程所需的全部 资源和进行一次性分配
- 简单、安全且易于实现
- 资源浪费、进程延迟
- 摒弃“不剥夺”条件
- 办法:进程在需要资源时才提出请求,且得不到满足 时应释放其已占有资源
- 实现复杂,代价很大(反复地申请与释放资源,释放资源后又得重头再来,造成资源的浪费、 进程周转时间延长、系统吞吐量降低、系统开 销增加)
- 摒弃“环路等待”条件
- 办法:所有资源按类型进行线性排队,所有进程对 资源的请求严格按资源序号递增次序提出
- 资源次序的不灵活性,有些资源可能到很后面才需要等等(新设备、程序逻辑设 计与编程限制及资源浪费)
死锁的检测
只要检测出当该状态 下的资源分配图是不可完全化简的就证明是死锁。
死锁检测算法
1 令 Work = Available
IsolatedSet = {Pi∣ Allocation [i] = 0∧ Requesti= 0 }
2 for all Pi 不属于 IsolatedSet do
begin
for all Requesti ≦ Work do
begin
Work= Work + Allocation[ i ] ;
IsolatedSet = IsolatedSet ∪ {Pi }
end
end
3 deadlock = ~ ( IsolatedSet = = {P1 , P2 , … , Pn});
注:
- work表示当前可用的资源
- IsolatedSet表示孤立进程集,是指该进程是可以完全化简的,没有任何有向边,既没有分配向量Allocation,也没有任何的请求资源向量Request,这样的进程的集合。
死锁的解除
常用方法:
剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
撤消进程:撤销部分死锁的进程,用释放出来的资源救活其它死锁的进程。此时,每撤销一个进程,就要死锁检测算法进行检测,看死锁是否解除,若没有,则继续撤销其它进程,直到死锁解除为止。
撤销原则:
① 撤销的进程越少越好:选择占用资源多的进程,牺牲一个,救活一批;
② 损失越少越好:选择最后进入系统的进程;
③ 截止时间小:选择最不紧迫的进程。
死锁避免
基本思想:
允许进程动态地申请资源,但系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程;否则,进程等待。
例如:
- 若T0 时刻分配序列为<P2, P1, P3> ,则进入安全状态,资源可分配给进程
- 若在T0 时刻把进程请求中所剩磁带机中的1台分配给 P3, 则系统进入不安全状态,所以应避免这样的分配
银行家算法
1.数据结构
Available表示可利用资源向量:Available[j]=k 表示系统现有 k 个 Rj 类资源
Requesti [j]=k 表示进程 Pi 请求 k 个 Rj 类资源
Max[i,j]=k 则表示进程Pi需要第Pj类资源的最大数目为k
Allocation[ i,j ]=k 表示进程 Pi 已分配有 k 个 Rj 类资源
Need[ i,j ]=k 表示进程 Pi 尚需 k 个 Rj 类资源,注意与request的区别,request的数目要小于等于need
三个矩阵的关系: Need[i, j]=Max[i, j]-Allocation[i, j]
Work[j]=k 表示系统“可”提供 k 个 Rj 类资源
Finish[ i ] 表示进程 Pi 可否拥有足够资源完成运行
2. 主体算法
1 进程Pi发出资源请求 Requesti
2 若非 Requesti ≤ Need [i] ,出错返回 (系统已分配资源的情况)
3 若非 Requesti≤ Available ,则应使Pi等待并返回 (系统剩余资源情况)
4 系统试探性地满足Pi请求,并作以下修改:
Available = Available – Requesti
Allocation[ i] = Allocation[ i ] + Requesti
Need[ i ] = Need[ i ] – Requesti
5 系统调用安全性算法进行资源分配检查,若安全 则执行分配,否则恢复试探分配前状态,并使Pi 等待
3. 安全性子算法
1 令 Work = Available , Finish= FALSE
2 从进程集合中查找一个满足 Finish[i ]=FALSE 且 Need[ i ] <= Work 的进程Pi 。若找到,则可 假定Pi能获得所需资源并顺利执行,故有:
Work = Work + Allocation[i]
Finish[i] = True
然后重复执行第2步;否则转至第3步执行
3 如果 Finish= TRUE ,则表示该集合中的所有进程都顺利执行,系统处于安全状态; 否则系统处于不安全状态