死锁是多线程竞争资源导致的互相等待现象,需满足互斥、占有等待、不可剥夺和循环等待四个条件;Java中常见于线程以不同顺序获取多个锁,如线程1持lock1等lock2,线程2持lock2等lock1;可通过按序加锁、设置超时、减少锁范围、避免嵌套锁及使用jstack工具检测来有效预防。
死锁是指两个或多个线程在执行过程中,因争夺资源而造成的一种互相等待的现象,导致这些线程都无法继续执行下去。
死锁的产生必须同时满足以下四个条件,缺一不可:
在 Java 多线程编程中,死锁通常发生在多个线程以不同的顺序获取多个锁。例如:
Object lock1 = new Object();
Object lock2 = new Object();
// 线程1
new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread1 获取 lock1");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("Thread1 获取 lock2");
}
}
}).start();
// 线程2
new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread2 获取 lock2");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock1) {

System.out.println("Thread2 获取 lock1");
}
}
}).start();
在这个例子中,线程1先拿 lock1 再申请 lock2,线程2先拿 lock2 再申请 lock1。如果两个线程几乎同时运行,就可能造成线程1持有 lock1 等 lock2,线程2持有 lock2 等 lock1,从而形成死锁。
可以通过以下方式预防或避免死锁:
tryLock(long timeout) 方法,在指定时间内无法获取锁就放弃,避免无限等待。