温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java多线程为何死锁

发布时间:2026-09-12 18:13:23 来源:亿速云 阅读:99 作者:小樊 栏目:编程语言

在 Java 多线程中,**死锁(Deadlock)**通常是指:两个或多个线程彼此持有对方所需要的锁,并且都在等待对方释放锁,从而导致所有相关线程都无法继续执行

下面从原因、示例、条件、避免方式几个方面说明。


一、为什么会发生死锁(核心原因)

死锁的本质是:线程之间对锁的获取顺序不一致 + 互相持有对方需要的资源

例如:

  • 线程 A 持有锁 L1,想获取锁 L2
  • 线程 B 持有锁 L2,想获取锁 L1

结果:

  • A 等 B 释放 L2
  • B 等 A 释放 L1
  • 谁都不放手 → 死锁

二、经典死锁示例

public class DeadlockDemo {
    private static final Object lockA = new Object();
    private static final Object lockB = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lockA) {
                System.out.println("Thread-1: hold lockA");
                try { Thread.sleep(100); } catch (InterruptedException e) {}
                synchronized (lockB) {
                    System.out.println("Thread-1: hold lockB");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (lockB) {
                System.out.println("Thread-2: hold lockB");
                try { Thread.sleep(100); } catch (InterruptedException e) {}
                synchronized (lockA) {
                    System.out.println("Thread-2: hold lockA");
                }
            }
        }).start();
    }
}

结果:程序卡死,两个线程互相等待。


三、死锁产生的四个必要条件(必须同时满足)

  1. 互斥条件
    资源一次只能被一个线程占用(如 synchronized)

  2. 占有且等待
    线程持有了资源,还在等待其他资源

  3. 不可抢占
    线程已获得的锁不能被强制剥夺

  4. 循环等待
    存在线程资源的循环依赖关系

✅ Java 中只要打破其中任意一个条件,就可以避免死锁。


四、常见导致死锁的场景

1. 多个锁获取顺序不一致

// 线程1
synchronized(A) { synchronized(B) {} }

// 线程2
synchronized(B) { synchronized(A) {} }

2. 在 synchronized 中调用外部方法

外部方法可能再次加锁或阻塞。

3. 使用 ReentrantLock 但未正确释放

lock.lock();
// 异常未 unlock

4. 线程间相互 join / wait / notify 使用不当


五、如何避免死锁(重点)

✅ 1. 固定锁的获取顺序(最重要)

// 统一先拿 lockA,再拿 lockB
synchronized(lockA) {
    synchronized(lockB) { }
}

✅ 2. 使用 tryLock(ReentrantLock)

if (lock.tryLock()) {
    try { ... } finally { lock.unlock(); }
}

✅ 3. 缩小同步范围

  • 只在必要代码加锁
  • 避免在锁内做 IO、sleep

✅ 4. 使用高级并发工具

  • ConcurrentHashMap
  • BlockingQueue
  • CountDownLatch
  • Semaphore

✅ 5. 超时机制

lock.tryLock(1, TimeUnit.SECONDS);

六、如何排查死锁

1. jstack

jstack <pid>

会显示:

Found one Java-level deadlock

2. VisualVM / JConsole

  • 线程监控
  • 死锁检测

七、一句话总结

Java 多线程死锁的本质是:多个线程以不同顺序获取多个锁,导致循环等待。

如果你愿意,我可以:

  • 帮你分析你代码中的死锁
  • 给你一个可运行的死锁修复示例
  • synchronized vs ReentrantLock 的死锁差异
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI