线程死锁
# 线程死锁
死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的互相等待的现象,在无外力作用的情况下,这些线程会一直相互等待而无法继续运行下去
# 造成死锁的条件
互斥条件:资源的锁,只能同时被一个线程获取,如果资源的锁被线程获取了,其他线程想要获取该资源只能等待。 不可剥夺:资源的锁一旦被线程获取,不能被其他线程抢占 请求并持有:指一个线程己经持有了至少一个资源 , 但又提出了新的资源请求 环路等待条件:指在发生死锁时 , 必然存在一个线程→资源的环形链 ,即线程集合{TO , TL T2 ,…,Tn }中 的 TO 正在等待一个 Tl 占用 的 资源 ,Tl 正在等待 T2 占用的 资源 ,…… Tn 正在等待 己被 TO 占用 的 资源。
# 如何避免死锁
破坏以上条件中的一个,但是上面只有请求并持有
,环路等待条件
可以被破坏。
案例演示
/**
* @Author ggball
* @Description 测试死锁
* @Date 2022/4/26
* @Param []
* @return void
**/
@Test
public void deadlock() throws InterruptedException {
Thread thread1 = new Thread(() -> {
synchronized (threadTest1) {
System.out.println("threadName:" + Thread.currentThread().getName() + ",获取threadTest1");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (threadTest2) {
System.out.println("threadName:" + Thread.currentThread().getName() + ",获取threadTest2");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (threadTest2) {
System.out.println("threadName:" + Thread.currentThread().getName() + ",获取threadTest2");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (threadTest1) {
System.out.println("threadName:" + Thread.currentThread().getName() + ",获取threadTest1");
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
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
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
流程:thread1
首先获取threadTest1
的锁,然后等待两秒,然后再获取threadTest2
锁
thread2刚好相反,thread2
首先获取threadTest2
的锁,然后等待两秒,然后再获取threadTest1
锁。
这样方便构成请求并等待条件
,而目前只有两个线程获取两个资源,也形成了环路条件
,再加上操作系统先天的条件(资源互斥条件
,和不可剥夺条件
)这样就形成了死锁。
破坏死锁办法: 破坏请求并等待条件:两个线程的获取所锁的顺序一致 破坏环路条件:更换线程获取的资源
上次更新: 2022/04/30, 15:12:48