java 如何防止死锁
避免嵌套锁
尽量减少锁的嵌套使用,确保线程按照固定的顺序获取多个锁。例如,所有线程都先获取锁A再获取锁B,避免交叉获取锁的顺序。
使用超时机制
在尝试获取锁时设置超时时间,避免无限等待。Lock接口的tryLock()方法可以指定超时时间,超时后线程可以释放已持有的锁并重试或执行其他逻辑。
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
if (lock1.tryLock(100, TimeUnit.MILLISECONDS)) {
try {
if (lock2.tryLock(100, TimeUnit.MILLISECONDS)) {
try {
// 执行操作
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
减少锁的粒度
将大锁拆分为多个小锁,降低锁的竞争概率。例如,使用ConcurrentHashMap替代synchronized修饰的HashMap,减少全局锁的使用。

使用无锁数据结构
优先使用线程安全的无锁数据结构,如AtomicInteger、ConcurrentLinkedQueue等。这些类通过CAS(Compare-And-Swap)实现线程安全,避免锁的开销和死锁风险。
静态分析工具
使用工具如FindBugs、SpotBugs或SonarQube检测代码中的潜在死锁问题。这些工具可以识别锁的顺序不一致或嵌套锁等问题。

避免锁的长时间持有
确保锁的持有时间尽可能短,避免在锁内执行耗时操作(如IO、网络请求)。将非关键路径的逻辑移到锁外执行。
死锁检测与恢复
通过监控线程状态和锁持有情况实现死锁检测。Java的ThreadMXBean可以检测死锁线程:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads();
if (threadIds != null) {
ThreadInfo[] infos = bean.getThreadInfo(threadIds);
for (ThreadInfo info : infos) {
System.out.println("Deadlocked thread: " + info.getThreadName());
}
}
使用高级并发工具
优先使用java.util.concurrent包中的高级工具,如Semaphore、CountDownLatch或CyclicBarrier。这些工具封装了复杂的同步逻辑,减少手动管理锁的需求。





