什么是线程死锁
线程死锁描述的是这样一种情况:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。 例如线程1持有者资源a,等待资源b,而线程2持有着资源b,等待资源a,这样就会出现线程之间持有彼此请求的资源不释放而导致的相互等待,造成线程死锁。
代码模拟死锁
定义了资源1,和资源2; 然后创建两个线程,线程1按顺序申请资源1和资源,而线程2按顺序申请资源2和资源1
java
public class LockThread {
private static Object resource1=new Object();
private static Object resource2=new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1){
System.out.println(Thread.currentThread().getName()+"get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"waiting get resource2 ...");
synchronized (resource2){
System.out.println(Thread.currentThread().getName()+"get resource2");
}
}
},"线程1").start();
new Thread(() -> {
synchronized (resource2){
System.out.println(Thread.currentThread().getName()+"get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"waiting get resource1 ...");
synchronized (resource1){
System.out.println(Thread.currentThread().getName()+"get resource1");
}
}
},"线程2").start();
}
}
结果:
java
线程1get resource1
线程2get resource2
线程1waiting get resource2 ...
线程2waiting get resource1 ...
线程 A 通过 synchronized (resource1) 获得 resource1 的监视器锁,然后通过Thread.sleep(1000);让线程 A 休眠 1s 为的是让线程 B 得到执行然后获取到 resource2 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对方的资源,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。
如何破坏死锁
死锁产生的条件
- 互斥条件:该资源任意一个时刻只由一个线程占用。
- 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
- 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。