08 死锁出现的原因以及怎么解决?

vvEcho 2024-01-20 14:08:36
Categories: Tags:

出现死锁的原因是因为两个线程出现持有对方想要的资源,导致这两个线程一直处在等待对方释放锁的状态;

破坏竞态条件既可以解除死锁,例如:当一个线程持有锁时,自己没有释放锁时不能再去尝试获取另一个锁;

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.local.demo.test.thredtest;

/**
* 死锁的示例
*
* @author: echo
* @date: 2025/3/1
*/
public class DeadThread {

// 定义两个锁对象
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();

public static void main(String[] args) {
// 线程1:先获取 lock1,再尝试获取 lock2
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
Thread.sleep(100); // 模拟操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (lock2) {
System.out.println("Thread 1: Acquired lock 2!");
}
}
});

// 线程2:先获取 lock2,再尝试获取 lock1
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock 2...");
try {
Thread.sleep(100); // 模拟操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (lock1) {
System.out.println("Thread 2: Acquired lock 1!");
}
}
});
// 启动两个线程
thread1.start();
thread2.start();

// 等待线程执行完成
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread finished.");
}
}

这里的thread1.join();thread2.join();只是主线程显式调用两个子线程的join方法,让jvm 等待两个子线程执行完成再执行主线程。达到观测的目的,如果不加这两行代码,主线程结束,子线程还会继续跑;除非关闭计算机或者关闭jvm进程;

如何让主线程结束,子线程也终止

1.显示的调用thread1.interrupt方法,让子线程抛出异常,子线程终止。
2.设置子线程thread1.setDaemon(true);改为守护线程,当主线程结束,守护线程也会结束。