文章目录
- 死锁的概念
- 死锁的定义
- 相似概念:饥饿
- 死锁产生的原因
- 死锁产生的必要条件
- 死锁的预防
- 破坏互斥条件
- 破坏不可剥夺/不可抢占条件
- 破坏请求并保持条件
- 破坏循环等待条件
- 死锁避免
- 安全性算法
- 死锁的处理策略
- 死锁的检测
- 死锁的解除
死锁的概念
死锁的定义
多个进程由于竞争资源而造成的阻塞现象,若无外力作用,这些进程都将无法继续推进。
相似概念:饥饿
等待时间过长以至于给进程推进和相应带来明显影响,“饿而不死”。
死锁产生的原因
- 系统资源的竞争;
- 进程推进的顺序非法;
死锁产生的必要条件
- 互斥条件:共享资源的排他性(独占性)访问;
- 不可剥夺条件:访问时该共享资源不会被剥夺;
- 请求保持条件:保持当前资源时请求另一个资源;
- 循环等待条件:存在共享资源的循环等待链;
死锁的预防
死锁的预防毫无疑问要从死锁产生的原因作为入手点。我们已经知道了死锁产生的四个必要条件,那么要解决死锁问题,就要从如何破坏死锁产生的四个条件展开。
破坏互斥条件
- 将只能互斥访问的资源改为同时共享访问;
- 将独占锁修改为共享锁;
- 不是所有的资源都可以改成共享的;
破坏不可剥夺/不可抢占条件
- 请求新资源无法满足时必须释放已有资源;
- 由OS协助强制剥夺某进程持有的资源;
- 实现复杂,代价高;
- 此操作过多导致原进程任务可能无法推进;
破坏请求并保持条件
- 进程开始运行时一次性申请所有需要的资源;
- 阶段性请求和释放资源;
破坏循环等待条件
- 对所有资源进行排序,按序号请求资源;
- 对资源的编号应该尽可能稳定,这限制了新设备的增加;
- **进程使用资源的顺序可能与系统编号顺序不同;
- 限制了用户编程;
死锁避免
个人觉得死锁的预防与死锁的避免有些类似。死锁的预防是针对死锁产生的条件进行分析,死锁的避免更偏向于操作系统通过一系列策略来对进程管理和各个进程所需的资源进行分配,以求达到死锁避免的效果。
安全性算法
- 系统安全状态
- 安全状态一定不会出现死锁;
- 不安全状态可能会出现死锁;
- 银行家算法
- 系统预判进程请求是否导致不安全状态;
- 是则拒绝请求,否则答应请求;
银行家算法举例:如上图所示
- 表格中展示了当前状态各个进程占用资源情况以及所需资源情况;
- 假如先执行P0,则还需分配5个资源,但此时可用资源为3,不行;
- 假如先执行P1,当前已分配2,还需分配2,小于可用资源,可行;
- 假如再执行P0,当前P1释放了4个资源,可用资源为5,等于P0所需,可行;
- 最后执行P2,可行; - 假如再执行P2,当前可用资源为5,小于P2所需资源,不可行;
- 假如再执行P0,当前P1释放了4个资源,可用资源为5,等于P0所需,可行;
- 假如先执行P2,还需分配7个资源,大于可用资源,不可行;
死锁的处理策略
死锁的检测
- 需要一种数据结构,保存有关资源的请求和分配信息;
- 提供一种算法,利用这些信息检测是否形成了死锁;
可以使用图这种数据结构来保存资源的请求和分配信息。
如示意图所示:定义资源分配图(G=(N, E)),其中有两种资源、两种节点。图的边分为两种类型:分配边以及请求边。可以看到,图中有两种资源,分别是R1和R2;两个进程P0和P1。注意:图中的一条边代表一个资源的请求/分配。
死锁定理(死锁状态的充分条件):
- 当且仅当此状态下资源分配图是不可完全简化的;
- 简化过程类似于“拓扑排序”算法;
在了解死锁定理的概念后,我们继续分析上图,来对其进行简化。怎么简化呢?
首先去除孤点和不阻塞的点,上图中P0分配了2个R1资源,正在请求1个R2资源(R2目前分配了1个给P1,还剩一个可分配),因此P0请求成功,不阻塞。接下来上图简化结果如下:
接下来,由于P0释放了占用的资源,阻塞状态的P1得以继续执行(不阻塞了),因此P1也可继续去除。结果如下图:
可以看到,此时资源与节点都是孤立的,这种状态就是所谓的完全简化。也意味着不会发生死锁。
死锁的解除
- 资源剥夺
- 挂起死锁进程
- 剥夺其资源
- 将资源分配给其他进程
- 撤销进程
- 进程回退
- 回退到足以避免死锁的地步
- 需要记录进程历史信息,设置还原点