Java死锁的原因及解决方法,java解决死锁的三种方法
00-1010死锁原因解决方案死锁汇总前言:
死锁是指两个或两个以上的计算单元(进程、线程或协程)都在等待对方释放资源,但都没有提到释放资源,从而造成一种阻塞的现象,称为死锁。
比如线程1在拥有锁A的情况下试图获取锁B,线程2在拥有锁B的情况下试图获取锁A,这样双方就进入了互相阻塞等待的局面。
如下图所示:
死锁的代码实现如下:
导入Java . util . concurrent . time unit;public class DeadLockTest { public static void main(String[]args){ Object lockA=new Object();Object lockB=new Object();//创建线程1 ThreadT1=NewThread ()-{//1。占有锁A synchronized(locka){ system . out . println( Thread 1:Get lock A . );//Sleep 1s(先让线程2有时间占用锁B)试试{ time unit . seconds . Sleep(1);} catch(interrupted exception e){ e . printstacktrace();} //2.线程2 { system . out . println( Thread 1:Get lock B . )的Get lock B synchronized(lockb);} } });t1 . start();//创建线程2 ThreadT2=NewThread ()-{//1。占有锁B同步(lockb){ system . out . println( Thread 2:Get lock B . );//睡眠1s(确保线程1有足够的时间获取锁A)尝试{TimeUnit。seconds . sleep;} catch(interrupted exception e){ e . printstacktrace();} //2.线程1 { system . out . println( Thread 2:Get lock A . )的Get lock A synchronized(locka);} } });T2 . start();} }以上程序的执行结果如下图所示:
从上面的结果可以看出,线程1和线程2都在等待对方释放锁,从而造成了死锁问题。
目录
死锁的产生需要满足以下 4 个条件:
互斥条件:它意味着计算单元(进程、线程或协程)对分配的资源是独占的,也就是说,某个锁资源在某个时间段内只能被一个计算单元占用。请求和保持条件是指一个运算器已经保留了至少一个资源,但是提出了新的资源请求,并且该资源已经被其他运算器占用。此时,发出请求的算术单元被阻塞,但它继续持有它已经获得的其他资源。不可剥夺条件:是指算术单元所获得的资源,在用完之前不能被剥夺。环路等待条件:当死锁发生时,必然存在一个计算单元和资源的循环链,即一个计算单元在等待另一个计算单元占用的资源,而另一方在等待自己占用的资源,从而产生循环等待。只有同时满足以上四个条件,才会造成死锁。
死锁产生原因
死锁产生要满足以上 4 个必要条件,那么我们只需要改变其中的 1 个或多个条件就可以解决死锁的问题了,比如我们可以通过修改获取锁的顺序来改变环路等待条件。
在未修改获取锁的顺序前,程序的执行流程是这样的:
其中 ① 表示先执行,② 表示后执行。 而改变锁的获取顺序之后的执行流程是这样的:
此时线程 1 和线程 2 获取锁的顺序是一致的,都是先获取锁 A,再获取锁 B,此时它们的执行流程如下:
线程 1 先获取到锁 A;线程 1 获取到锁 B;线程 1 释放了锁 B;线程 1 释放了锁 A;线程 2 获取到了锁 A;线程 2 获取到了锁 B;线程 2 释放了锁 B;线程 2 释放了锁 A。对应的实现代码如下:
import java.util.concurrent.TimeUnit;class DeadLockTest { public static void main(String[] args) { Object lockA = new Object(); Object lockB = new Object(); // 创建线程 1 Thread t1 = new Thread(() -> { // 1.获取锁 A synchronized (lockA) { System.out.println("线程1:获得锁A。"); // 休眠 1s try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } // 2.获取锁 B synchronized (lockB) { System.out.println("线程1:获得锁B。"); System.out.println("线程1:释放锁B。"); } System.out.println("线程1:释放锁A。"); } }); t1.start(); // 创建线程 2 Thread t2 = new Thread(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } // 1.获取锁 A synchronized (lockA) { System.out.println("线程2:获得锁A。"); // 2.获取锁 synchronized (lockB) { System.out.println("线程2:获得锁B。"); System.out.println("线程2:释放锁B。"); } System.out.println("线程2:释放锁A。"); } }); t2.start(); }}
以上程序的执行结果如下图所示:
总结
死锁(Dead Lock)指的是两个或两个以上的运算单元(进程、线程或协程),都在等待对方释放资源,但没有一方提前释放资源,从而造成了一种阻塞的现象就称为死锁。产生死锁需要同时满足 4 个条件:互斥条件、请求和保持条件、不可剥夺条件、环路等待条件,因此我们只需要破坏其中 1 个或多个条件就可以解决死锁的问题了。
到此这篇关于Java中死锁产生的原因有哪些?的文章就介绍到这了,更多相关java死锁产生内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。