这是我参与更文挑战的第14天,活动详情查看: 更文挑战
XDM,今天是端午节啦,祝大家端午安康喽,大家都应该吃到自己的粽子了吧!你们粽意的我又来了,今天我们学习死锁
1、什么是死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象,若无外力作用,它们都将无法推进下去。此时系统处于死锁状态或系统产生了死锁
上面的概念说的很规范,不容易理解,使用代码来举例子相比较而言会更容易理解一些
public class NormalDeadLock {
private static Object No13 = new Object();//第一个锁
private static Object No14 = new Object();//第二个锁
//第一个拿锁的方法
private static void do1() throws InterruptedException {
String threadName = Thread.currentThread().getName();
synchronized (No13){
System.out.println(threadName+" get nO13");
Thread.sleep(100);
synchronized (No14){
System.out.println(threadName+" get nO14");
}
}
}
//第二个拿锁的方法
private static void do2() throws InterruptedException {
String threadName = Thread.currentThread().getName();
synchronized (No14){
System.out.println(threadName+" get nO13");
Thread.sleep(100);
synchronized (No13){
System.out.println(threadName+" get nO14");
}
}
}
}
复制代码
两个线程线程A,和线程B,分别执行了do1,和do2,线程A拿到了13号锁,线程B拿到了14号锁,这样线程在拿14号锁的时候拿不到了,就进入了阻塞状态了,线程B也拿不到13号锁也进入了阻塞状态,这样两个线程都不干活了,谁也不让谁,就一直在这耗着浪费了资源
2、造成死锁的必要条件
2.1、操作者数 >=2,资源数>=2 并且资源数<=操作者数
如果只有一个操作者,肯定不会造成资源竞争,如果只有线程A拿到13号锁直接也就拿到了14号锁,直接干活就是了,如果可用资源数大于操作者数,也不会造成死锁,比如又来了个15号锁,也能满足do2的业务逻辑,那么do2得到14 号锁接着去获取15号锁,跟线程A就没有关系了也就产生不了死锁
2.2、争夺资源的顺序不对
如果我们把锁的顺序调换一下,把do2的第一层锁变成13,线程A 和线程B一开始都去争夺13号锁,线程A抢到了,线程A干完了事,线程B自然而然也就能拿到13号锁继续干它的事,也就不会产生死锁
2.3、拿到资源不放手
我们再想一下,如果线程A比较谦让,等了一段时间,没有拿到14号锁,它把13号锁让出去了,让线程B先执行,死锁的问题也会得到解决
总结
死锁的产生的必要条件就是以上三个,想要解决死锁问题,打破三个条件的其中一个就可以解决死锁问题,死锁的问题在高并发的业务场景中是很容易遇到,而且不易排查的问题!希望本文对XDM有用!