java 如何避免死锁
避免死锁的方法
固定顺序获取锁
确保所有线程以相同的顺序获取多个锁。例如,若需要获取锁A和锁B,所有线程必须先获取A再获取B。这消除了循环等待条件。
使用超时机制
通过 tryLock() 方法设置获取锁的超时时间。若在指定时间内未获取锁,线程会释放已持有的锁并重试或退出,避免无限等待。

减少锁的粒度
缩小锁的作用范围或使用更细粒度的锁(如分段锁)。例如,ConcurrentHashMap 通过分段锁减少竞争。
避免嵌套锁
尽量减少在一个锁的持有期内获取另一个锁。若必须嵌套,确保遵循固定顺序。

使用无锁数据结构
考虑使用 Atomic 类(如 AtomicInteger)或 Concurrent 集合(如 ConcurrentLinkedQueue),避免显式锁。
死锁检测与恢复
通过监控工具(如JConsole)或代码检测死锁。发现死锁后,强制释放锁或中断线程。
代码示例
// 固定顺序获取锁示例
public void transfer(Account from, Account to, int amount) {
Account first = from.getId() < to.getId() ? from : to;
Account second = from.getId() < to.getId() ? to : from;
synchronized (first) {
synchronized (second) {
if (from.getBalance() >= amount) {
from.debit(amount);
to.credit(amount);
}
}
}
}
// 超时机制示例
public boolean tryTransfer(Lock lockA, Lock lockB, long timeout) throws InterruptedException {
long startTime = System.currentTimeMillis();
while (true) {
if (lockA.tryLock(timeout, TimeUnit.MILLISECONDS)) {
try {
if (lockB.tryLock(timeout, TimeUnit.MILLISECONDS)) {
return true; // 成功获取两把锁
}
} finally {
lockA.unlock(); // 释放A锁
}
}
if (System.currentTimeMillis() - startTime >= timeout) {
return false; // 超时退出
}
}
}






