死锁的原因
多线程各自持有不同的锁,并互相试图获取对方已持有的锁,导致无限等待。死锁发生后,没有任何机制能解除死锁,只能强制结束JVM进程。
如何避免死锁
避免死锁的方法是多线程获取锁的顺序要一致。
代码示例
-
这种情况会造成死锁:线程1在试图获取线程2已经获取并未释放的锁
-
什么时候会释放锁:synchronized代码块结束之后才会释放由synchronized获取的锁
package org.meituan.javalearn.thread;
/**
* @projectName: codebetter
* @package: org.meituan.javalearn.thread
* @className: DeadLock
* @author: fangjiayueyuan
* @description: 死锁
* @date: 2023/5/4 上午10:30
* @version: 1.0
*/
public class DeadLock {
static final Object LOCK_A = new Object();
static final Object LOCK_B = new Object();
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
static void sleep1s() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Thread1 extends Thread {
public void run() {
System.out.println("Thread-1: try get lock A...");
synchronized (DeadLock.LOCK_A) {
System.out.println("Thread-1: lock A got.");
DeadLock.sleep1s();
System.out.println("Thread-1: try get lock B...");
synchronized (DeadLock.LOCK_B) {
System.out.println("Thread-1: lock B got.");
DeadLock.sleep1s();
}
System.out.println("Thread-1: lock B released.");
}
System.out.println("Thread-1: lock A released.");
}
}
class Thread2 extends Thread {
public void run() {
System.out.println("Thread-2: try get lock B...");
synchronized (DeadLock.LOCK_B) {
System.out.println("Thread-2: lock B got.");
DeadLock.sleep1s();
System.out.println("Thread-2: try get lock A...");
synchronized (DeadLock.LOCK_A) {
System.out.println("Thread-2: lock A got.");
DeadLock.sleep1s();
}
System.out.println("Thread-2: lock A released.");
}
System.out.println("Thread-2: lock B released.");
}
}
- 改写代码:按照相同的顺序去获取锁,避免死锁
package org.meituan.javalearn.thread;
/**
* @projectName: codebetter
* @package: org.meituan.javalearn.thread
* @className: DeadLock
* @author: fangjiayueyuan
* @description: 死锁
* @date: 2023/5/4 上午10:30
* @version: 1.0
*/
public class DeadLock {
static final Object LOCK_A = new Object();
static final Object LOCK_B = new Object();
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
static void sleep1s() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Thread1 extends Thread {
public void run() {
System.out.println("Thread-1: try get lock A...");
synchronized (DeadLock.LOCK_A) {
System.out.println("Thread-1: lock A got.");
DeadLock.sleep1s();
System.out.println("Thread-1: try get lock B...");
synchronized (DeadLock.LOCK_B) {
System.out.println("Thread-1: lock B got.");
DeadLock.sleep1s();
}
System.out.println("Thread-1: lock B released.");
}
System.out.println("Thread-1: lock A released.");
}
}
class Thread2 extends Thread {
public void run() {
System.out.println("Thread-2: try get lock A...");
synchronized (DeadLock.LOCK_A) {
System.out.println("Thread-2: lock A got.");
DeadLock.sleep1s();
System.out.println("Thread-2: try get lock B...");
synchronized (DeadLock.LOCK_B) {
System.out.println("Thread-2: lock B got.");
DeadLock.sleep1s();
}
System.out.println("Thread-2: lock B released.");
}
System.out.println("Thread-2: lock A released.");
}
}
效果图: