死锁的条件

死锁是指在多个进程或线程中,因互相等待而导致无法继续执行的情况。死锁的发生必须满足以下四个必要条件,这些条件被称为死锁四大必要条件:

  1. 互斥条件(Mutual Exclusion):系统中至少有一个资源是以互斥方式分配的,即一次只能有一个进程使用该资源。如果其他进程请求该资源,必须等待。
  2. 请求与保持条件(Hold and Wait):至少有一个进程已经持有一个资源,并且在等待其他被其他进程持有的资源。也就是说,进程持有资源后,还需要等待其他资源释放。
  3. 不剥夺条件(No Preemption):一旦进程获得资源,系统不能强行剥夺资源。资源只能在进程使用完之后才会被释放。
  4. 循环等待条件(Circular Wait):存在一组进程 {P1, P2, ..., Pn},其中 P1 等待 P2 占有的资源,P2 等待 P3 占有的资源,…,Pn 等待 P1 占有的资源,形成一个闭环,导致所有进程都无法继续执行。

死锁的解决方法

1. 死锁预防(Deadlock Prevention)

死锁预防的目标是通过避免死锁的四个必要条件中的任何一个来确保系统永远不会发生死锁。

常见预防方法:

  • 避免互斥条件:在某些场景中,尽量避免使用互斥资源,如使用无锁数据结构。但是,在很多情况下,互斥资源是必不可少的,因此这个条件难以完全避免。
  • 避免请求与保持条件:要求进程在获得所有需要的资源后再开始执行(即一次性请求所有资源)。如果不能满足所有资源的请求,进程就放弃当前请求,等到资源可用时重新申请。
  • 避免不剥夺条件:允许在进程持有资源时,如果它请求其他资源而无法得到时,强制剥夺已经持有的资源并释放。这要求进程能够适应“资源被抢占”的情况。
  • 避免循环等待条件:确保进程请求资源时,必须按照一定的顺序请求。例如,进程必须按照固定的顺序获取资源,避免形成环形等待。

缺点:死锁预防的策略可能会增加系统的资源开销或降低效率(比如要求进程一次性申请所有资源)。

2. 死锁避免(Deadlock Avoidance)

死锁避免比预防更加灵活,它要求系统对资源的分配和进程的请求作出实时判断,确保不会进入死锁状态。常见的死锁避免策略是 银行家算法。

  • 银行家算法:银行家算法基于资源的最大需求来进行安全性检查。每次进程请求资源时,系统会判断是否能够满足进程请求并保持系统处于安全状态。如果请求能够满足,并且之后能确保系统不会发生死锁,资源会被分配给进程;否则,进程必须等待,直到可以安全分配资源。

优势:可以保证系统始终处于安全状态,避免死锁。

缺点:银行家算法要求提前知道每个进程的最大资源需求,并且计算复杂度较高,难以应用于动态变化的资源需求。

3. 死锁检测(Deadlock Detection)

死锁检测是一种在死锁发生后进行处理的方法。系统运行时不加以限制,而是在进程执行过程中检测是否发生了死锁,并在检测到死锁时采取措施。

  • 死锁检测算法:一种常见的死锁检测算法是 资源分配图 或 等待图。资源分配图是一个有向图,图中的节点代表进程和资源,边代表进程对资源的请求或者资源被进程占用。通过遍历图来检测是否存在环路,如果存在环路,则说明系统发生了死锁。
  • 检测后的处理:一旦发现死锁,系统就会通过以下几种方式之一来解决死锁:
    • 终止进程:选择某些进程终止,释放它们占用的资源,打破死锁。
    • 回滚进程:回滚到进程执行的某个安全点,并让它重新执行,以释放资源,避免死锁发生。
    • 抢占资源:从某些进程中抢夺资源,分配给其他进程,从而打破死锁。

优势:检测发生死锁后进行处理,避免了死锁预防的资源浪费。

缺点:需要实时检测死锁,一旦发生死锁,可能会导致系统性能下降或需要执行较为复杂的操作来解除死锁。

4. 死锁恢复(Deadlock Recovery)

在死锁发生后,系统需要采取措施进行恢复,最常见的恢复方法有:

  • 进程终止:选择某些死锁中的进程终止,释放其占用的资源。可以选择随机终止一个进程,或者选择优先级较低的进程终止。
  • 资源剥夺:通过从死锁中的进程剥夺资源并分配给其他进程来解除死锁。可能需要中断一些进程并将它们占用的资源重新分配。
  • 回滚进程:将进程的状态回滚到某个安全的检查点,并重新执行,避免死锁的发生。

注意:死锁恢复的方法通常涉及中断进程或者回滚操作,这可能会导致一些资源浪费或者进程执行时间增加,因此需要谨慎选择恢复策略。

5. 解决死锁的具体方法

a) 资源分配顺序

确保系统中每个进程按统一顺序请求资源,避免形成环形等待。例如,可以按照资源的 ID 排序,每个进程按 ID 号升序请求资源,确保所有进程请求资源时不会发生循环等待。

b) 使用锁的超时机制

使用锁的时候设置超时机制。进程在请求资源时如果长时间没有得到资源,可以选择主动放弃请求,稍后重新请求,从而避免死锁的发生。

c) 回滚机制

在死锁检测到后,可以选择将进程回滚到某个状态,释放占用的资源,打破死锁。可以通过保存进程状态的快照来实现回滚,确保进程恢复到某个无死锁的状态。

d) 设置资源限制

限制每个进程请求的资源数量,避免进程因占用大量资源而导致死锁。例如,限制进程最多只能请求资源的总量为系统资源的某个比例。


总结

  • 死锁的四个条件是:互斥条件、请求与保持条件、不剥夺条件、循环等待条件。
  • 解决死锁的方法包括:死锁预防、死锁避免、死锁检测、死锁恢复。
  • 预防和避免死锁的方法适用于系统设计时防止死锁发生,而检测和恢复方法适用于死锁已经发生后的处理。

在实际应用中,如何解决死锁需要根据系统需求和负载情况来综合考虑,选择合适的策略。