lizema lizema
首页
  • js

    • js
  • Git相关

    • 《Git》
  • 设计模式

    • 设计模式
  • 并发编程

    • 死锁
  • java
  • jdk
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • HTML
  • CSS
  • CIM
  • 学习方法
  • 敏捷开发心得
  • 心情杂货
  • 实用技巧
  • GPT相关
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

malize

各自努力,顶峰相见。
首页
  • js

    • js
  • Git相关

    • 《Git》
  • 设计模式

    • 设计模式
  • 并发编程

    • 死锁
  • java
  • jdk
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • HTML
  • CSS
  • CIM
  • 学习方法
  • 敏捷开发心得
  • 心情杂货
  • 实用技巧
  • GPT相关
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 死锁

    • 什么是死锁
      • 死锁的四个必要条件
        • 死锁的预防
          • 1. 破坏互斥条件
          • 2. 破坏请求与保持条件
          • 3. 破坏不剥夺条件
          • 4. 破坏循环等待条件
        • 死锁的避免
          • 死锁的检测与恢复
            • 检测方法
            • 恢复策略
          • 实际案例分析
            • 案例1:哲学家就餐问题
            • 问题描述
            • 解决方案
            • 案例2:线程池中的死锁
            • 问题描述
            • 解决方案
          • 代码示例
            • Java中的死锁示例
            • 避免死锁的代码示例
          • 总结
          • 通用技术
          • 并发编程
          xx
          2026-04-15
          目录

          死锁

          # 死锁

          # 什么是死锁

          死锁是指两个或多个线程在执行过程中,因争夺资源而造成的一种互相等待的现象。当线程A持有资源1并等待资源2,而线程B持有资源2并等待资源1时,就会发生死锁。

          # 死锁的四个必要条件

          1. 互斥条件:资源不能被共享,一次只能被一个线程使用
          2. 请求与保持条件:线程已经保持了至少一个资源,但又提出了新的资源请求
          3. 不剥夺条件:线程获得的资源在使用完之前不能被其他线程强行剥夺
          4. 循环等待条件:若干线程之间形成头尾相接的循环等待资源关系

          # 死锁的预防

          # 1. 破坏互斥条件

          • 允许资源共享使用,例如使用读写锁

          # 2. 破坏请求与保持条件

          • 一次性申请所有需要的资源
          • 只有在所有资源都可用时才分配

          # 3. 破坏不剥夺条件

          • 当线程申请新资源失败时,主动释放已持有的资源
          • 允许其他线程抢占已分配的资源

          # 4. 破坏循环等待条件

          • 对资源进行编号,要求线程按顺序申请资源
          • 使用资源分配图算法检测并避免循环等待

          # 死锁的避免

          使用银行家算法等资源分配策略,在分配资源前进行安全性检查,确保系统不会进入不安全状态。

          # 死锁的检测与恢复

          # 检测方法

          • 资源分配图算法
          • 银行家算法

          # 恢复策略

          • 终止所有死锁进程
          • 按优先级终止部分死锁进程
          • 资源剥夺:从死锁进程中剥夺资源

          # 实际案例分析

          # 案例1:哲学家就餐问题

          # 问题描述

          5个哲学家围坐在一张圆桌旁,每两个哲学家之间有一根筷子,每个哲学家需要两根筷子才能吃饭。如果每个哲学家都先拿起左边的筷子,再尝试拿起右边的筷子,就会发生死锁。

          # 解决方案

          • 最多允许4个哲学家同时拿起左边的筷子
          • 按顺序获取筷子(奇数号先拿左边,偶数号先拿右边)
          • 使用信号量控制资源访问

          # 案例2:线程池中的死锁

          # 问题描述

          线程池中的线程A等待线程B的结果,而线程B又等待线程A的结果,形成死锁。

          # 解决方案

          • 避免线程间的循环依赖
          • 使用超时机制,避免无限等待
          • 合理设计任务分解,减少线程间的依赖

          # 代码示例

          # Java中的死锁示例

          public class DeadlockExample {
              private static final Object resource1 = new Object();
              private static final Object resource2 = new Object();
          
              public static void main(String[] args) {
                  // 线程1:先获取resource1,再获取resource2
                  Thread thread1 = new Thread(() -> {
                      synchronized (resource1) {
                          System.out.println("Thread 1: Holding resource 1");
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("Thread 1: Waiting for resource 2");
                          synchronized (resource2) {
                              System.out.println("Thread 1: Holding resource 1 and 2");
                          }
                      }
                  });
          
                  // 线程2:先获取resource2,再获取resource1
                  Thread thread2 = new Thread(() -> {
                      synchronized (resource2) {
                          System.out.println("Thread 2: Holding resource 2");
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("Thread 2: Waiting for resource 1");
                          synchronized (resource1) {
                              System.out.println("Thread 2: Holding resource 1 and 2");
                          }
                      }
                  });
          
                  thread1.start();
                  thread2.start();
              }
          }
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41

          # 避免死锁的代码示例

          public class DeadlockAvoidance {
              private static final Object resource1 = new Object();
              private static final Object resource2 = new Object();
          
              public static void main(String[] args) {
                  // 线程1:按顺序获取资源
                  Thread thread1 = new Thread(() -> {
                      synchronized (resource1) {
                          System.out.println("Thread 1: Holding resource 1");
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("Thread 1: Waiting for resource 2");
                          synchronized (resource2) {
                              System.out.println("Thread 1: Holding resource 1 and 2");
                          }
                      }
                  });
          
                  // 线程2:按相同顺序获取资源
                  Thread thread2 = new Thread(() -> {
                      synchronized (resource1) {
                          System.out.println("Thread 2: Holding resource 1");
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("Thread 2: Waiting for resource 2");
                          synchronized (resource2) {
                              System.out.println("Thread 2: Holding resource 1 and 2");
                          }
                      }
                  });
          
                  thread1.start();
                  thread2.start();
              }
          }
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41

          # 总结

          死锁是并发编程中的常见问题,了解死锁的产生原因和解决方法对于编写可靠的并发程序至关重要。通过破坏死锁的四个必要条件、使用死锁避免算法、以及合理的资源分配策略,可以有效减少死锁的发生。

          在实际开发中,应注意以下几点:

          1. 尽量减少资源的竞争
          2. 按顺序申请资源
          3. 使用超时机制避免无限等待
          4. 定期检测死锁并采取恢复措施

          通过合理的设计和编码实践,可以显著提高系统的可靠性和性能。

          编辑 (opens new window)
          最近更新
          01
          其他
          02
          其他
          03
          CIM半导体行业业务流程详解
          07-04
          更多文章>
          Theme by Vdoing
          • 跟随系统
          • 浅色模式
          • 深色模式
          • 阅读模式