Java线程死锁详解(5大死锁解决方案)

死锁是大厂经常涉及的,下面我详解Java线程死锁以及解决方案@mikechen

Java线程死锁

线程死锁指的是:两个、或多个线程互相持有对方需要的资源。

并且都在等待对方释放资源,导致所有线程永久阻塞。

Java线程死锁详解(5大死锁解决方案)-mikechen

      Thread-A
          │
      持有Lock-A
          │
          ▼
等待 Lock-B ◄─────┐
                  │
                  │
      Thread-B    │
          │       │
      持有Lock-B  │
          │       │
          ▼       │
等待 Lock-A ──────┘

结果:

Thread-A 永远等待
Thread-B 永远等待

程序无法继续执行。

 

Java线程死锁解决方案

Java线程死锁详解(5大死锁解决方案)-mikechen

1. 统一加锁顺序

这是最有效、最常用的方法。

所有线程都按相同顺序获取锁,比如永远先拿 lockA 再拿 lockB

// 示例:总是先获取hashCode小的锁
if (System.identityHashCode(lockA) < System.identityHashCode(lockB)) {
    synchronized (lockA) { synchronized (lockB) { ... } }
} else {
    synchronized (lockB) { synchronized (lockA) { ... } }
}

2. 尽量减少嵌套锁

能少拿一把锁就少拿一把锁,避免“持有 A 再申请 B”这种链式等待。

3. 缩小锁范围

把同步代码块缩到最小,只保护真正共享的数据,不要把 I/O、RPC、数据库访问、复杂计算放在持锁期间。

4. 使用超时锁

Lock.tryLock(timeout) 这类方式可以在等待超时后放弃获取锁,从而避免无限等待。

5. 设计成无锁或低锁

能用并发容器、原子类、消息队列、CAS、分段锁解决的,尽量不要靠粗粒度互斥锁硬扛。

评论交流
    说说你的看法