跳转至

死锁的预防

预防死锁的一种常见方法是破坏死锁产生的四个必要条件中的一个或多个。死锁产生的四个条件是:互斥条件、请求与保持条件、不可剥夺条件和循环等待条件。由于互斥条件是不可避免的(因为至少有一个资源是独占的),因此通常不考虑去破坏它。针对其他三个条件,可以采用不同的策略来避免死锁:

破坏“请求和保持”条件

  • 方法:通过预分配资源来避免进程在运行期间继续请求资源。所有资源在进程启动时一次性分配完,进程在运行期间无法再请求新的资源。
  • 优点
    • 简单易实现。
    • 系统设计上较为直观。
  • 缺点
    • 资源利用率低:由于预分配可能导致某些资源处于空闲状态,无法被其他进程利用。
    • 饥饿现象:如果某个进程没有及时获取到所有资源,它可能会长时间等待,导致饥饿。

这种方法适用于对资源需求预测较为准确的系统,但在多任务、大规模的复杂系统中并不总是有效。

破坏“不可剥夺”条件

  • 方法:采用可剥夺的资源分配方式,即允许进程在资源不足时释放已持有的资源。进程如果无法获得所需资源,就会释放已经占用的资源,并在以后重新申请。
  • 优点
    • 可以防止死锁的发生,因为进程可以通过释放已占用资源来重新调整系统状态。
  • 缺点
    • 实现复杂:需要在操作系统中实现资源的抢占、保存和恢复状态的机制。
    • 代价高:在某些资源(如内存、文件)中,保存和恢复状态可能涉及较大的开销。
  • 适用范围
    • 对于那些能够方便保存和恢复状态的资源(如 CPU 寄存器、内存)比较适用。

这种方法适合对资源状态能够进行高效保存和恢复的环境,但在某些硬件或软件环境下实现起来可能非常复杂。

破坏“循环等待”条件

  • 方法:通过对系统中的所有资源进行线性排序,确保资源的请求遵循一定的顺序,从而避免循环等待。可以通过两种方式实现:
    • 依序分配:要求所有进程按资源的编号顺序申请资源。
    • 先弃大,再取小:进程在申请资源时,如果已有资源的编号大于申请资源的编号,就必须释放已占用的资源。
  • 优点
    • 通过合理的资源排序,减少了死锁的风险,系统吞吐量和资源利用率有所提高。
  • 缺点
    • 编号顺序难以满足所有需求:对于一些复杂的资源依赖,可能很难找到一个所有进程都满意的资源编号顺序。
    • 资源浪费:即使某些资源可能在某时段未被使用,仍然会受到排序的限制。
    • 用户编程限制:要求进程必须严格按照指定顺序申请资源,这可能会限制用户程序的灵活性。

该方法适用于资源请求较为可预测和固定的场景,但在动态变化的系统中,可能会导致不必要的资源浪费和使用不便。