java如何避免死锁
避免死锁的方法
固定顺序获取锁
确保所有线程按照相同的顺序获取多个锁。例如,若需要获取锁A和锁B,所有线程必须先获取A再获取B,避免交叉依赖导致的死锁。这种方式破坏了“循环等待”条件。
使用锁超时机制
通过tryLock()方法设置超时时间,若在指定时间内未获取锁,线程会释放已持有的锁并重试或退出。例如:
if (lock1.tryLock(1, TimeUnit.SECONDS)) {
try {
if (lock2.tryLock(1, TimeUnit.SECONDS)) {
try {
// 执行业务逻辑
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
减少锁的持有范围
尽量缩小同步代码块的范围,仅在必要操作时持有锁,避免长时间占用锁资源。这降低了多个锁竞争的概率。
使用无锁数据结构
考虑使用ConcurrentHashMap、AtomicInteger等并发工具类,或基于CAS(Compare-And-Swap)的无锁算法,减少对显式锁的依赖。
检测与恢复
通过监控工具(如JConsole、VisualVM)检测死锁,或使用ThreadMXBean编程式检测。发现死锁后,可强制终止线程或设计恢复逻辑。
实际应用示例
以下代码演示了固定顺序获取锁的实现:
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);
}
}
}
}
通过结合上述策略,能有效降低死锁风险。需根据具体场景选择合适的方法,并在设计阶段充分考虑并发安全性。







