死锁预防

2025年5月15日 | 阅读 7 分钟

如果我们用一张四条腿站立的桌子来模拟死锁,那么我们也可以用导致死锁的四种条件来模拟这四条腿。当这四种条件同时发生时,就会导致死锁。

然而,如果我们能够破坏桌子的一条腿,那么桌子一定会倒下。死锁也是一样,如果我们能够违反四种必要条件中的一种,不让它们同时发生,那么我们就可以预防死锁。

要点

  • 死锁预防的目标是消除死锁的四个先决条件之一:循环等待、保持并等待、互斥以及非抢占。
  • 在许多系统中,破坏互斥或抢占资源可能会造成浪费或不切实际。
  • 通过为资源分配优先级并强制执行资源请求的固定顺序,可以避免循环等待。
  • 死锁避免会带来资源利用率下降和系统设计复杂度增加等权衡。
  • 死锁避免至关重要,但并非所有操作系统都能使其可行或实用。

让我们看看如何预防每种条件。

1. 互斥

从资源的角度来看,互斥是指一个资源永远不能被多个进程同时使用,这是很公平的,但这也是死锁的主要原因。如果一个资源可以被多个进程同时使用,那么进程就不会一直等待任何资源。

然而,如果我们能够破坏资源以互斥方式运行,那么就可以预防死锁。

Spooling

对于打印机等设备,假脱机(spooling)可以起作用。打印机有一个与之关联的内存,用于存储每个进程的任务。之后,打印机收集所有任务,并按照先来先服务的顺序打印。使用这种机制,进程不必等待打印机,而是可以继续执行正在进行的工作。之后,它在输出产生时收集输出。


os Deadlock Prevention Spooling

尽管假脱机可以作为一种有效的方法来破坏互斥,但它也存在两种问题。

  1. 并非所有资源都适用。
  2. 一段时间后,进程之间可能会出现争夺假脱机空间的竞争条件。

我们不能强迫一个资源同时被多个进程使用,因为这不公平,并且可能会导致严重的性能问题。因此,在实践中我们无法破坏进程的互斥性。

假脱机的问题

  • 只有具有关联内存的资源(如打印机)才能使用假脱机。
  • 它也可能导致竞争条件。当两个或多个进程使用一个资源,并且无法预测结果时,这就称为竞争条件。
  • 例如,在打印机假脱机中,如果进程 A 覆盖了进程 B 在队列中的工作,那么进程 B 将永远收不到输出。
  • 这不是一个万无一失的解决方案,因为一旦队列填满,进入的进程就会进入等待状态。
  • 例如,如果队列有十个块,那么任何拥有超过十个块的进程都会进入等待状态。

2. 保持并等待

当一个进程持有某个资源并等待其他资源来完成其任务时,就发生了保持并等待条件。死锁发生是因为可能有一个或多个进程持有了一个资源,并在循环顺序中等待另一个资源。

然而,我们必须找到一种机制,让进程要么不持有任何资源,要么不等待。这意味着,进程必须在执行开始前获得所有必要的资源。一旦执行开始,进程就不应该等待任何资源。

!(保持并等待) = !持有 或 !等待 (保持并等待的否定是,要么你不持有,要么你不等待)

如果一个进程一开始就声明了所有需要的资源,那么这可以被实际实现。然而,这听起来非常实用,但在计算机系统中却无法实现,因为进程无法在开始时确定所需的资源。

进程是 CPU 执行的指令集。每条指令可能在多个时间点需要多个资源。操作系统无法固定其需求。

该方法的问题在于

  1. 实际上不可能。
  2. 饥饿的可能性会增加,因为某些进程可能会长时间持有资源。

挑战

  • 进程在执行过程中一次只执行一条指令,因此无法预知执行前所有必需的资源。
  • 释放进程的所有资源一次的另一个问题是,这些资源可能对其他进程没有用,而被不必要地释放。
  • 例如,当进程 1 同时释放资源 2 和资源 3 时,资源 3 被不必要地释放了,因为进程 2 并不需要它。

3. 非抢占

死锁的产生是由于一旦进程开始,就不能停止它。然而,如果我们从导致死锁的进程那里夺取资源,我们就可以预防死锁。

这根本不是一个好的方法,因为如果我们夺走一个被进程使用的资源,那么它到目前为止所做的所有工作都可能变得不一致。

考虑一个进程正在使用打印机。如果我们从该进程那里夺走打印机并将其分配给另一个进程,那么所有已打印的数据都可能变得不一致和无效,而且进程无法从它离开的地方重新开始打印,这会导致性能低下。

挑战

  • 这些方法很麻烦,因为进程可能正在积极使用这些资源,而通过抢占来停止它可能会导致不一致的结果。
  • 例如,如果一个进程在完成对文件的更新之前其访问就被终止,那么该文件将变得无用且不一致。
  • 反复提交所有资源请求效率低下且耗时。

4. 循环等待

为了破坏循环等待,我们可以为每个资源分配一个优先级编号。进程不能请求优先级较低的资源。这确保了没有任何进程可以请求一个已被其他进程占用的资源,也不会形成循环。


os Deadlock Prevention

在所有方法中,破坏循环等待是唯一可以实际实现的方法。

挑战

  • 由于多个进程可能对同一资源有不同的重视程度,因此很难为它们分配相对优先级。
  • 例如,文档处理器可能比媒体播放器更看重打印机。根据情况和用例,资源的优先级不同。

预防死锁的可行性

  • 由于某些资源的内在不可共享性,互斥无法被完全消除。
  • 由于我们无法预先预测避免等待所需的资源,因此无法废除保持并等待。通过在寻求新资源时释放所有资源来阻止保持是低效的。
  • 被抢占的进程可能变得不一致,并且为了重新请求所有资源而重新启动进程是浪费的。
  • 只能通过消除循环等待来实际避免死锁。

总结

移除四个必需条件之一——互斥、保持并等待、非抢占和循环等待——中的任何一个都可以避免死锁。

破坏互斥、保持并等待和非抢占几乎是不可能的。

通过为每个资源分配优先级,可以消除循环等待。如果进程请求一个比它已有的资源更重要的资源,则请求将被批准。

常见问题

1. 操作系统死锁预防是什么意思?

为了避免死锁的发生,系统必须设计成保证至少一个死锁的先决条件无法满足。

2. 操作系统如何识别死锁?

操作系统可以通过使用监控资源请求和分配的算法,或者通过检查资源分配图来识别死锁。如果识别出僵局,系统可以采取补救措施,包括停止进程或抢占资源。

3. 死锁避免技术有什么缺点?

预防死锁可能导致

  • 资源利用率下降:在进程等待时,资源可能闲置。
  • 饥饿:某些进程可能永远无法获得它们所需的资源。
  • 增加复杂性:实施预防措施可能会使系统设计更加复杂。

4. 在实践中是否总是可能预防死锁?

答案是否定的。虽然可以设计能够避免死锁的系统,但其限制和开销可能会使其不切实际。在某些情况下,人们更喜欢其他策略,如检测和恢复或死锁避免。

5. 死锁避免和死锁预防有什么区别?

通过消除一个先决条件,死锁预防主动确保死锁不会发生。相比之下,死锁避免允许系统进入危险状态,同时仔细分配资源以避免实际的死锁。

6. 您能举一个预防死锁的例子吗?

一种流行的方法是为资源分配数值等级,并强制进程按升序请求资源。这样可以避免循环等待情况。

7. 任何操作系统都能预防死锁吗?

在需要动态资源分配的操作系统中,死锁避免很难实现。由于所需的复杂性和开销,某些系统可能发现实施严格的死锁预防规定不切实际。


下一主题死锁避免