Java-线程死锁

线程死锁介绍

死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的互相等待的现象,在无外力的作用的情况下,线程会一直互相等待而无法继续运行下去。如下图所示

image-20210219212359389

线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。

线程死锁产生条件

  • 互斥条件:指线程以对已经获取到的资源进行排它性使用,即改资源同时只由一个线程占用。如果此时还有其他线程请求获取该资源,则请求者只能等待,知道占有资源的线程释放该资源。
  • 请求并持有条件:指一个线程以及持有了至少一个资源,但又提出了新的资源请求,而新资源以被其他线程占有,所以当前线程会被阻塞,但阻塞的同时并不释放自己已经获取的资源。
  • 不可剥夺条件:指线程获取到的资源在自己使用完之前不能被其他线程抢占,只有在自己使用完毕后才由自己释放该资源。
  • 环路等待条件:只在发生死锁时,必然存在一个线程—资源的环形链,即线程集合【T0,T1,T2,T3,….,Tn】中的T0正在等待一个T1占用的资源,T1正在等待T2占用的资源,….Tn正在等待已被T0占用的资源。
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
public class DeadLockDemo {
private static Object resource1 = new Object();//资源 1
private static Object resource2 = new Object();//资源 2

public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 1").start();

new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource1");
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
}
}
}, "线程 2").start();
}
}

如何避免线程死锁

要想避免死锁,只需要破坏掉至少一个构成死锁的必要条件即可,跟进操作系统的特性,目前只有请求并持有和环路等待条件时可以被破坏的。

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
public class DeadLockDemo {
private static Object resource1 = new Object();//资源 1
private static Object resource2 = new Object();//资源 2

public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 1").start();

new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 2").start();
}
}

Java-线程死锁
http://www.wangxiaohuan.com/2020/03/08/2020-03-08/
作者
吃素的左撇子
发布于
2020年3月8日
许可协议