死锁
死锁概念的引入
信号量产生死锁,利用进度图可视分析死锁:
- 上锁带来了潜在的死锁:即等待一个永远不会为真的条件
- 不同的执行轨迹会造成不同的执行结果,死锁的产生与调度有关
死锁概念
死锁:多个进程(线程)因循环等待资源而造成无法执行的现象
- 死锁造成进程无法执行
- 死锁造成系统资源的极大浪费,因为资源无法释放
死锁产生的必要条件
资源
多个进程因等待资源才造成死锁,资源互斥访问是死锁的必要条件。
资源分配图
-
一个进程集合{P1 , P2 , …, Pn}
-
一资源类型集合{R1 , R2 , …, Rm}
-
资源请求边:有向边$P_i\to R_j $
-
资源占有边:有向边 R i → P k R_i\to P_k Ri→Pk
存在环路不一定死锁, 死锁一定存在环路
死锁的四个必要条件
- 互斥使用(Mutual exclus),至少有一个资源互斥使用
- 不可抢占(No preemptio),资源只能自愿放弃,如车开走以后
- 持有和等待(Hold and wait),进程占有资源时还申请资源
- 循环等待(Circular wait),在资源分配图中存在一个环路
死锁处理方法
死锁预防–破坏死锁的必要条件
破坏互斥使用
资源的固有特性,通常无法破除,如打印机
破除不可抢占
- 如果一个进程占有资源并申请另一个不能立即分配的资源,那么已分配资源就可被抢占(即持有不用即可抢占)
- 自怼状态能保存和恢复的资源有效,对打印机等外设不适用
破除持有和等待
- 必须保证在请求资源时,不持有任何其他资源
- 在进程执行前,一次性申请所有需要的资源
- 缺点
- 需要预知未来,编程困难
- 许多资源分配后很长时间后才使用,资源利用率低
破除循环等待
- 对资源类型进行排序,资源申请必须按序进行
- 如所有进程必须先申请磁盘驱动,再申请打印机
- 缺点:要求编程时就需要考虑,可能释放某些资源,进程会无法执行。
破除死锁的必要条件会引入不合理因素,实际中很少使用。
死锁避免
判断此次请求是否造成死锁,若会造成死锁,则拒绝该请求
- 安全状态定义:如果系统中的所有进程存在一个可完成的执行序列P1, …Pn,则称系统处于安全状态
- 安全序列:上面的执行序列P1 , …, Pn
- 安全序列P1 , …, Pn 应该满足的性质:Pi (1≤ i ≤n) 需要资源 ≤ 剩余资源 + 分配给所有 Pj (1≤j ≤ i) 资源
避免死锁就是要确保系统永远不会进入不安全状态。
银行家算法
- 尝试寻找一个安全的执行时序,决定一个状态是否是安全的。
- 不存在安全的序列,则状态是不安全的。
Banker();
int n, m; //系统中进程总数n和资源种类总数m
int Available[m]; //资源当前可用总量
int Allocation[n][m]; //当前给分配给每个进程的各种资源数量
int Need[n][m]; //当前每个进程还需分配的各种资源数量
int Work[m]; //当前可分配的资源,包括可回收的
bool Finish[n]; //进程是否结束
// 1.初始化设定:
Work = Available (动态记录当前可(收回)分配资源)
Finish[i] = false(设定所有进程均未完成)
// 2.查找这样的进程Pi(未完成但目前剩余资源可满足其需要,这样的进程是能够完成的):
a) Finish[i] == false b) Need[i] <= Work[i]
如果没有这样的进程Pi,则跳转到第4步
// 3.(若有)Pi一定能完成,并归还其占用的资源,即:
a) Finish[i] = true b) Work[i] = Work[i] + Allocation[i]
GOTO 2,继续查找
// 4.如果所有进程Pi都是能完成的,即Finish[i] = true
则系统处于安全状态,否则系统处于不安全状态
银行家算法讨论
- 每个进程进入系统时必须告知所需资源的最大数量对应用程序员要求高
- 安全序列寻找算法(安全状态判定算法)计算时间复杂度为 O ( m n 2 ) O(mn^2) O(mn2),过于 复杂
- 若每次资源请求都要调用银行家算法,耗时过大,系统效率降低
- 采用此算法,存在情况:当前有资源可用,尽管可能很快就会释放,由于 会使整体进程处于不安全状态,而不被分配,致使资源利用率大大降低
死锁检测+恢复
死锁检测
改进银行家算法,只要可用资源足够,则分配,发现问题再处理
- 定时检测或者当发现资源利用率低时检测
死锁恢复
- 终止进程:优先级确定,可按占用资源多的
- 剥夺资源:回滚进程
习题
若系统 S1 采用死锁避免方法,S2 采用死锁检测方法。下列叙述中,正确的是(D)
I. S1 会限制用户申请资源的顺序,而 S2 不会
II. S1 需要进程运行所需的资源总量信息,而 S2 不需要
III. S1 不会给可能导致死锁的进程分配资源,而 S2 会
A.仅 I、II B.I、II、III C.仅 I、III D.仅 II、III
死锁忽略(鸵鸟算法)
对死锁不做任何处理
- 死锁出现时,手动干预——重新启动
- 死锁出现不是确定的,避免死锁付出的代价毫无意义
- 但是大多数操作系统都用它,如UNIX和Windows
习题
1.某系统中有三个并发进程都需要四个同类资源,则该系统必然不会发生 死锁的最少资源是(B)
A.9 B.10 C.11 D.12
资源数为9时,存在每个进程占有三个资源,为死锁。资源数为10时,必然存在一个进程能拿到4个资源,可以顺利执行完其他进程。
2.某系统有R1、R2和R3共三种资源,在T0时刻P1、P2、P3和P4这四个进程 对资源的占用和需求情况见下表,此时系统的可用资源向量为(2,1,2), 试问:
-
用向量或矩阵表示系统中各种资源的总数和此刻各进程对各资源的需求 数目。
系统中资源总量为某时刻系统中可用资源量与各进程己分配资源量之 和,即:
(2,1,2)+(1,0,0)+ (4,1,1)+(2,1,1)+(0,0,2)=(9,3,6)
各进程对资源的需求量为各进程对资源的最大需求量与进程已分配资源量 之差,即
[
3
2
2
6
1
3
3
1
4
4
2
2
]
−
[
1
0
0
4
1
1
2
1
1
0
0
2
]
=
[
2
2
2
2
0
2
1
0
3
4
2
0
]
\begin{bmatrix} 3 && 2 && 2\\ 6 && 1 && 3\\ 3 && 1 && 4\\ 4 && 2 && 2 \end{bmatrix}- \begin{bmatrix} 1 && 0 && 0\\ 4 && 1 && 1\\ 2 && 1 && 1\\ 0 && 0 && 2 \end{bmatrix}= \begin{bmatrix} 2 && 2 && 2\\ 2 && 0 && 2\\ 1 && 0 && 3\\ 4 && 2 && 0 \end{bmatrix}
363421122342
−
142001100112
=
221420022230
- 若此时进程P1和进程P2均发出资源请求向量Request(1,0,1),为了保 证系统的安全性,应如何分配资源给这两个进程?说明所采用策略的原因。
再利用安全性算法检查系统是否安全,可用资源 Available(1,1,1)已不 能满足任何进程,系统进入不安全状态,此时系统不能将资源分配给进程P1。
从上表可以看出,此时存 在一个安全序列 {P2,P1,P3,P4},故该状态 是安全的,可以立即将P2 申请的资源分配给它。
- 若2)中两个请求立即得到满足后,系统此刻是否处于死锁状态?
若2)中的两个请求立即得到满足,则此刻系统并未立即进入死锁状态, 因为这时所有的进程未提出新的资源申请,全部进程均未因资源申请没有得 到满足而进入阻塞态。只有当进程提出资源申请且全部进程都进入阻塞态时 ,系统才处于死锁状态。
3.下面是一个并发进程的程序代码,正确的是(B )
A. 进程不会死锁,也不会“饥饿”
B. 进程不会死锁,但是会“饥饿”
C. 进程会死锁,但是不会“饥饿”
D. 进程会死锁,也会“饥饿”
4.假设系统中有下述解决死锁的办法:
(1)银行家算法;
(2)检测死锁,终止处于死锁状态的进程,释放该进程占有的资源;
(3)资源预分配。
简述哪种办法允许最大的并发性?请按“并发性”从大到小对上述3种办法排序。
【参考答案】题中给出的3种办法中,
检测死锁能允许更多的进程无等待地向前推进,并发性最大。因为该方法允许进程最大限度地申请并分配资源,直至出现死锁,再由系统解决。
银行家算法允许进程自由申请资源,只是在某个进程申请时检查系统是否处于安全状态,若是,则可立即分配,若不是,才拒绝。并发性大小次于检测死锁的方法。
最后是资源预分配,因为此方法要求进程在运行之前申请所需的全部资源才可以,这会使得许多进程因申请不到资源而无法开始,得到部分资源的进程因得不到全部资源也不释放已占用的资源,因此导致资源的浪费。
因此,3种方法的并发性按从大到小排序为:检测死锁、银行家算法、资源预分配。
限度地申请并分配资源,直至出现死锁,再由系统解决。
银行家算法允许进程自由申请资源,只是在某个进程申请时检查系统是否处于安全状态,若是,则可立即分配,若不是,才拒绝。并发性大小次于检测死锁的方法。
最后是资源预分配,因为此方法要求进程在运行之前申请所需的全部资源才可以,这会使得许多进程因申请不到资源而无法开始,得到部分资源的进程因得不到全部资源也不释放已占用的资源,因此导致资源的浪费。
因此,3种方法的并发性按从大到小排序为:检测死锁、银行家算法、资源预分配。