死锁
死锁问题
死锁是指一组处于阻塞状态的进程,每个进程持有其他进程需要的资源,而又等待其他资源所幽幽的资源,致使相互等待,均无法向前推进。
死锁的原因
- 资源竞争
- 进程间的推进顺序不当
死锁的特点 Deadlock Characterization
必要条件
- 互斥访问 mutex exclusion
- 保持和等待 hold and wait : 一个进程持有其他进程想要访问的资源,并进入阻塞状态
- 不可剥夺 No preemption:当资源被一个进程持有之后,只有当进程执行完后才能释放这些资源
- 循环等待 Circular wait:
在单实例的情况下,这四个条件是充分必要条件。
在多实例的情况下,这四个条件是必要条件。
资源分配图 RAG resource allocation graph
P1,P2,P3互相等待进入死锁
处理死锁的三种方式
- 死锁预防:对进程使用资源加上诸多限制,以防系统出现死锁
- 死锁避免:基于系统的先验知识,当进程申请资源的时候,若果发现当前进程对于资源的请求可能导致思索的发生则拒绝该申请。
- 死锁检测和恢复:鸵鸟政策,等待死锁产生,检测死锁再从死锁中恢复。
死锁预防 Deadlock Prevention
当四种条件同时出现的时候才会出现死锁
破坏互斥条件
进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
破坏请求与保持hold and wait
- 占有不等待:在进程执行前,将其所需要的所有资源都分配给他,就不会进入阻塞
- 等待不占有:当进程不用有资源时才能申请资源,进程使用完并释放后才能申请另一种资源。
问题:
很多进程只有当运行时才知道他需要多少资源
破坏非剥夺条件
- 某些阻塞的进程拥有资源,将i分配给其他等待的进程
- 如果资源申请没满足,则释放已获得的资源
问题是,当进程的资源被剥夺了,再去执行的时候会重新申请资源,导致效率低下,和饥饿问题
适用于状态可保存及恢复的资源,比如CPU寄存器等,一般不适用于互斥锁,打印机,信号量等这类资源
打破循环等待
破坏“循环等待”条件的一种方法,是将系统中的所有资源统一编号,进程可在任何时刻提出资源申请,但所有申请必须按照资源的编号顺序(升序)提出
问题是编号困难,限制了新设备的增加,也增加编程人员的负担。
例题
某系统有同类资源m个,他们共n个进程共享,如果每个进程最多只申请x个资源,说明不等式
n
(
x
−
1
)
+
1
≤
m
n(x-1) + 1 \leq m
n(x−1)+1≤m成立该系统就不会死锁
在极端情况下,每个进程都申请了(x-1)个资源,并同时申请下一个资源。如果还有一个资源那么,其中一个进程就会得到资源向下执行,执行完毕后释放所有资源,并使得其他进程依次道道所需的资源而执行结束,不会产生死锁。
因此产生死锁的条件是,可用资源数至少为
n
(
x
−
1
)
+
1
n(x-1) + 1
n(x−1)+1个
死锁避免 Deadlock Avoidance
- 需要每个进程都声明他所需要的每种资源所需要的最大数
- 死锁避免算法动态地检查资源分配状态,来保证不会产生循环等待的情况
- 资源分配状态包括:可用资源数,已分配资源数,资源最大需求数
其中一个安全状态如下图:
可以找到某一种执行顺序,使得不发生死锁就是安全状态。
安全序列 safe sequence :
p1,p0,p2
不安全状态,无论按那种顺序分配资源都会发生死锁
当然,上述状态还未发生死锁,但是当最后一个资源完成分配之后,就成了死锁状态。
- 在安全状态,没有产生死锁
- 在不安全状态,极有可能死锁
- 死锁避免就是要避免系统进入不安全状态。
- 当有进程申请资源时,系统必须判断分配给他资源后是否仍满足安全状态,否则拒绝。
总体思想:当进程提出资源请求后,系统进行假分配,然后检测假分配之后的状态是否安全,若果不安全,则拒绝请求,否则,满足本次进程的资源请求;
单实例:利用资源分配图解决问题 RAG
- 实边:已分配资源,或已提出申请
- 虚边:尚需要,但是还没有提出申请
- 不安全状态:不论实边还是虚边,只要是存在环,则认为存在死锁的可能
安照死锁避免的要求这种状态的图是不能出现的。但是还没有彻底进入死锁
算法概述:
- 1、讲相关的虚边转换为请求边
- 2、如果请求的资源可得,假分配,将请求边转换为资源分配边,否则请求资源的进程进入阻塞状态
- 3、如果有环,则不能分配资源,该进程进入阻塞,否则对进程分配资源
将资源分配图转化为等待图 Wait-for graph
多实例:使用银行家算法
如果有n个进程,m种资源将Avalible ,Max,Allacation,Need 分别用二维数组表示出来。
银行家算法
- 1、申请合法性检查:if Request_i <= Need_i ,go to step 2 Otherwise ,raise error condition
- 2、资源可用性检查:if Request_i <= Avaliable, got o step 3.otherwise P_i must wait
- 3、假分配:
-
Avaliable = Avaliable - Request_i;
-
Allocation_i = Allocation_i + Request_i;
-
Need_i = Need_i - Request_i;
- 4、对修改后的状态进行安全性检查
-
if safe 将资源分配给 pi
-
if unsafe pi 必须进入阻塞,保持原先的资源分配状态
安全性检查算法
- 1、 work 为长度为m的向量 finish 为长度为n的向量
-
初始化: work = Avaliable
-
Finish[i] = False for i = 0,1,...,n-1
- 2、Find i 满足:
-
(a) Finish[i] = false
-
(b) Need_i <= work
-
如果这样的 i 不存在,转到步骤4
- 3、work = work + allocation_i
-
Finish[i] = True
-
go to step 2
- 4、if Finish[i] = i for all i, 系统是安全的,否则,系统是不安全状态。
银行家算法,破坏循环等待
死锁检测 Deadlock Detection
单实例
P之间有环就说明存在死锁
对于资源是单个实例的情况,检查是否存在死锁进程,需要画出进程等待图,然后检查出是否存在圈
多实例
多实例是否存在死锁,化成矩阵,运行安全性检查算法