死锁原理
死锁被定义为一组竞争系统资源或互相通信的进程间相互的“永久”阻塞。
当一组进程中的所有进程都在等待一个事件(等待请求资源的释放),而只有在进程集合中的其他阻塞的进程才可以触发该事件,这时就称一组进程死锁。因为没有事件可以触发,故死锁是永久性的。
资源通常分为两类:可重用资源和可消费资源
可重用资源(可重复使用的资源)
可重用资源是指一次只能供一个进程安全地使用,并且不会由于使用而耗尽的资源。
- 在一个时间只能一个进程使用且不能被删除;
- 进程获得资源,后来释放由其他进程重用;
- 可重用资源的例子包括处理器,I/O通道,主存和副存,设备和数据结构,如文件,数据库和信号量等;
- 如果每个进程拥有一个资源并请求其他资源,死锁可能发生。
可消费资源(使用资源)
可消费资源是指可以创建(生产)并且可以销毁(消费)的资源。
- 创建和销毁
- 在I/O缓冲区的中断,信号,消息,信息
- 如果接收信息阻塞可能会发生死锁
- 可能少见的组合事件会引起死锁
死锁特征
死锁的四个必要条件:
- 互斥:在一个时间只能有一个进程使用资源
- 持有并等待:进程保持至少一个资源正在等待获取其他进程持有的额外资源
- 无抢占:一个资源只能被进程自愿释放,进程已经完成了它的任务之后
- 循环等待:存在等待进程集合{P0,P1…PN},P0正在等待P1所占用的资源,P1正在等待P2占用的资源,…,PN-1正在等待PN所占用的资源,PN正在等待P0所占用的资源。
死锁处理办法
有四种方式:死锁预防,死锁避免,死锁检测,死锁恢复
- 确保系统永远不会进入死锁状态
- 运行系统进入死锁状态,然后恢复
- 鸵鸟算法:忽略这个问题,假装系统从来没有发生死锁;用于大多数操作系统
死锁预防
死锁预防策略是试图设计一种系统来排除发生死锁的可能性。
死锁预防方法分为两类:一种是间接的死锁预防。前三种;一种是直接的死锁预防。即防止循环等待的发生。
- 互斥----共享资源不是必须的,必须占用非共享资源
- 占用并等待----必须保证当一个进程请求的资源,它不持有任何其他资源。
需要进程请求并分配其所有资源,它开始执行之前或允许进程请求资源仅当进程没有资源;资源利用率低,可能发生饥饿。 - 无抢占----直接将进程杀掉,将资源抢占过来,手段暴力,不合理的方式。
- 循环等待----对所有资源类型进行排序,并要求每个进程按照资源的顺序进行申请。
死锁避免
死锁避免允许前三个条件,通过明智的选择,确保永远不会到达死锁点,因此死锁避免比死锁预防允许更多的并发。
- 最简单和最有效的模式是要求每个进程声明它可能需要的每个类型资源的最大数目;
- 资源的分配状态是通过限定提供与分配的资源数量和进程的最大需求。
- 死锁避免算法动态检查资源分配状态,以确保永远不会有一个环形等待状态。
两种死锁避免方法:
- 如果一个进程的请求会导致死锁,则不启动此进程;
- 如果一个进程增加资源的请求会导致死锁,则不允许此分配;
死锁避免的优点是它不需要死锁预防中的抢占和重新运行进程,并且比死锁预防的限制少。但是,它在使用中有许多限制:
- 必须事先声明每个进程请求的最大资源;
- 考虑的进程必须是无关的,它们执行的顺序必须没有任何同步要求的限制;
- 分配的资源数目必须是固定的;
- 在占有资源时,进程不能退出。
死锁检测
死锁检测策略不限制资源访问或约束进程行为。只要有可能,被请求的资源都被授权给进程。操作系统周期性地执行一个算法检测循环等待条件。
大致思路:允许系统进入死锁状态;死锁检测算法;恢复机制。
- 在每个资源请求时检查死锁情况的优点:它使得可以尽早地检测死锁情况,并且由于此方法基于系统状态的逐渐变化情况,因而算法相对比较简单。
- 缺点:这种频繁的检查会耗费相当多的处理器时间。
死锁恢复
一旦检测到死锁,就需要某种策略以恢复死锁。死锁恢复是最后的手段。
方法:
- 终止所有的死锁进程;
- 在一个时间内终止一个进程直到死锁消除
- 终止进程的顺序应该是:进程的优先级;进程运行了多久以及需要多少时间才能完成;进程占用的资源;进程完成需要的资源;多少进程需要被终止;进程是交互还是批处理。
以上这些方法都存在某种程度上的强制性和不合理性。
- 选择一个受害者----最小的成本;
- 回滚----返回到一些安全状态,重启进程到安全状态
- 饥饿----同一进程可能一直被选作受害者,包括回滚的数量。