死锁是指在多线程或多进程程序中,多个进程或线程在执行过程中,因争夺资源而造成一种相互等待的状态,从而导致程序无法继续执行。

死锁的四个必要条件

死锁的发生必须满足以下四个条件,这四个条件通常被称为“死锁的必要条件”:

  1. 互斥条件:
    • 至少有一个资源是处于“非共享”状态的,即每次只能有一个线程或进程使用这个资源。如果有其他线程请求该资源,必须等待。
  2. 占有并等待:
    • 至少有一个线程已经持有了一个资源,并且正在等待其他线程所持有的资源。
  3. 不剥夺条件:
    • 资源不能被强制从持有者的手中剥夺,只有在持有者自行释放资源时,其他线程才能获得该资源。
  4. 循环等待:
    • 存在一种线程或进程的循环等待关系,即线程 A 等待线程 B 持有的资源,线程 B 等待线程 C 持有的资源,最终线程 C 又等待线程 A 持有的资源,形成一个环形等待链。

死锁的危害

  • 系统崩溃或性能下降:死锁会导致程序停滞不前,使得受影响的线程无法继续执行。严重时,整个应用程序的性能会受到影响,甚至导致系统崩溃。
  • 资源浪费:死锁会造成资源的长时间占用,而无法被其他线程或进程使用,导致资源的浪费。
  • 用户体验差:死锁的存在可能导致应用程序的响应延迟或无响应,从而影响用户体验。

死锁的预防策略

  1. 避免互斥条件:
    • 如果可能的话,尽量避免将资源设置为“互斥”资源,即允许多个线程或进程同时访问某些资源。这在一些资源的设计上可能实现,如共享内存、并发数据结构等。
  2. 避免占有并等待:
    • 一次性请求:要求线程在开始时请求所有所需的资源。如果不能同时获得所有资源,则不分配任何资源,从而避免线程持有部分资源时再等待其他资源。
  3. 避免不剥夺条件:
    • 如果一个线程请求资源时发现部分资源被其他线程占用,它可以释放自己已经持有的资源并重新尝试请求,避免形成不剥夺条件。
  4. 避免循环等待:
    • 资源排序法:按固定顺序申请资源,如果一个线程请求的资源没有满足要求,它会按照顺序排队,直到所有资源都可以满足为止。这样可以避免循环等待。
    • 例如,a,b两个进程都需要资源1,资源2,如果a进程获得了资源1,然后b进程获得了资源2就会导致死锁,如果强制要求必须先获得资源1再获得资源2,如果某个进程先获得了资源1,那么另一个进程就会等待,直到资源1的释放,就打破死锁了。

死锁的检测和恢复

尽管死锁预防非常重要,但在一些复杂的并发环境中,无法保证完全避免死锁。因此,死锁的检测和恢复也很重要。

死锁检测

死锁检测是指通过某些算法在程序运行时检测是否发生了死锁。常见的死锁检测方法有:

  1. 资源分配图法:
    • 资源分配图是一种图结构,其中节点表示资源和进程,边表示资源与进程之间的关系。如果图中存在一个环,则说明发生了死锁。
  2. 等待图法:
    • 通过分析线程之间的等待关系,构建一个等待图。如果该图中有环,则表明程序发生了死锁。
死锁恢复

一旦检测到死锁,系统需要采取措施来恢复正常状态。常见的死锁恢复策略有:

  1. 撤销进程:
    • 通过终止一个或多个进程来破坏死锁的循环等待关系,进程终止后释放它所占用的资源,从而让其他进程继续执行。
  2. 资源抢占:
    • 系统可以通过抢占某个进程的资源并分配给其他进程,直到资源分配满足并避免死锁。
  3. 回滚:
    • 将进程回滚到之前的某个安全状态,释放资源并重新尝试获取资源。
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐