2.19.2 死锁的条件
- 必要条件
- 互斥:一次只有一个进程可以使用一个资源
- 占有且等待:当进程等待其他资源时继续占有已有的资源
- 不可抢占:进程不能强行占有其他进程占有的资源
- 充分条件
- 循环等待:存在一个闭合的进程链,每个进程至少占有此链中下一个进程所需的一个资源
2.19.3 死锁的解决
- 死锁预防:防止死锁的四个条件之一
- 死锁避免:防止循环等待的出现
- 死锁检测与解除
2.20 死锁预防
- 间接方法:防止死锁的三个必要条件之一
- 防止互斥:不可防止
- 防止占有且等待:要求进程一次性请求所有需要的资源(效率低、需要估计所需要的资源)
- 防止不可抢占:一个占有资源的进程请求资源不得则释放已占有资源或操作系统要求另一个进程释放资源(需要容易保存资源状态的结构)
- 直接方法:防止循环等待的出现
- 防止循环等待:定义一个请求资源的顺序,所有进程对资源的请求必须严格按资源序号递增的顺序提出(低效)
2.21 死锁避免
- 避免进入不安全状态
- 与死锁预防相比:允许三个必要条件
- 动态检查:运行过程中检查进程申请资源的结果是否安全,若会死锁则阻塞,否则予以分配
- 死锁避免两种方式
- 资源分配拒绝:若一个进程增加的资源请求导致死锁,则拒绝该请求
- 进程启动拒绝:若一个进程请求导致死锁,则拒绝启动该进程
2.21.1 银行家算法
属于资源分配拒绝策略,由Dijkstra于1965年提出
思想
用户申请一组资源时,系统判断分配后是否还处于安全状态,若是则允许分配,否则不分配,阻塞用户进程
安全状态
至少有一个资源分配安全序列,按照这个序列分配资源,可以不导致死锁地运行结束,相应的,不存在安全序列就是不安全状态
安全状态的判定
- Claim矩阵(后简称C矩阵):各个进程声明想要的资源数量
- Allocation矩阵(后简称A矩阵):已经分配给各个进程的资源数量
- C-A矩阵:又称Request矩阵:各个进程还需要资源的数量
- Resource向量(后简称R向量):各种资源的初始总量
- Available向量(后简称A向量):各种资源剩余可用的量
方法:
- 查看当前A向量能否满足C-A其中一行
- 满足则将A矩阵对应行加到A向量上,继续3,否则不安全
- 重复1
- C-A为0则得到安全序列
图解:
得到安全序列为P2,P1,P3,P4
- 安全序列不唯一,A向量满足C-A多行时可以尝试多个序列
- 安全状态也不一定不会死锁,安全状态时不按照安全序列分配就会死锁
- 并非所有不安全状态都是死锁状态
//全局数据结构
struct state {
int resource [ m ] ;
int available [ m ];
int claim [ n ][m ] ;
int alloc [ n ][m ] ;
}
//资源分配算法主体
if (alloc [ i,* ] + request [*]> claim [ i,* 〕)
<error >; /*total request > claim* /
else if (request [ * ] > available [ * ])
<suspend process >;
else { /*simulate alloc */
<define newstate by :
alloc [ i,* ]= alloc [ i,* ]+request [ * ];
available [*] = available [ * ] - request [* ] >;
}
if (safe ( newstate ) )
< carry out allocation >;
else {
<restore original state >;
<suspend process >;
}
//银行家算法测试安全性
boolean safe (state s) {
int currentavail[m];
process rest [<number of processes>];
currentavail = available;
rest = {all processes};
possible = true;
while (possible) {
<find a process Pk in rest such that
claim [k,* ] - alloc [k,* ] <= currentavail;>
if (found) { /*simulate execution of Pk */
currentavail = currentavail + alloc [ k,*];
rest = rest - {Pk};
}
else possible = false;
}
return ( rest ==null );
}
2.21.2 评价死锁避免
- 优点
- 无需死锁预防中的抢占和回滚
- 比死锁预防限制更少
- 缺点
- 必须先得到每个进程声明请求的资源,即要有Claim矩阵
- 进程执行顺序必须没有要求,否则不能按照安全序列来
- 分配的资源数量必须固定
- 占有资源的进程不能退出
2.22 死锁检测与解除
2.22.1 算法步骤
- 标记A矩阵中一全零行
- 初始化W向量=A向量
- 在C-A矩阵查找下标i的进程行,未被标记且这一行<=W向量,若找不到则终止算法
- 若找到这样的行,标记进程i,把A矩阵中的相应行加到W向量中,返回3
- 当且仅当3终止时,仍有未标记的进程,才存在死锁,未标记的进程都是死锁状态
2.22.1 资源分配图检测方法
资源分配图的化简
- 找出全部请求都满足的节点Pi,消去其所有请求边和分配边,使之成为孤立节点
- 重复1直至无法化简
示例
可完全简化的,则不存在死锁
不能完全简化时,存在死锁(如下图)
2.22.2 死锁解除
- 撤销死锁进程,直到不再存在死锁
- 回退,回退到前面定义的某些检查点,重新启动所有进程
- 抢占,连续抢占直到不再有死锁
那么撤销哪些进程?又该抢占哪些进程的资源?
选择原则:输出少、剩余时间长、优先级低、目前为止消耗cpu时间少的