当前位置: 首页 > 后端技术 > Java

4个解决死锁的工具!

时间:2023-04-01 13:32:11 Java

死锁(DeadLock)是指两个或多个计算单元(进程、线程或协程),都在等待对方停止执行以获取系统资源,但没有一个提前退出,称为死锁。死锁示例下面我们来演示一下Java中最简单的死锁。我们创建两把锁和两个线程,让线程1先拥有锁A,1s后尝试获取锁B。同时启动线程2,先让它拥有锁B,1s后尝试获取锁A。这时候就会出现等待对方释放锁的情况,就会出现死锁问题。具体代码如下:publicclassDeadLockExample{publicstaticvoidmain(String[]args){ObjectlockA=newObject();//创建锁A对象lockB=newObject();//创建锁B//创建线程1Threadt1=newThread(newRunnable(){@Overridepublicvoidrun(){//首先同步获取锁A(lockA){System.out.println("线程1:获取锁A!");try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}//尝试获取锁BSystem.out.println("Thread1:waitingtoacquireB...");synchronized(lockB){System.out.println("Thread1:acquiretolockB!");}}}});t1.开始();//运行线程//创建线程2Threadt2=newThread(newRunnable(){@Overridepublicvoidrun(){//先同步获取锁B(lockB){System.out.println("线程2:获取lockB!");try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}//尝试获取锁ASystem.out.println("Thread2:WaitingtoacquireA...");synchronized(lockA){System.out.println("线程2:获得锁A!");}}}});t2.开始();//Runthread}}以上程序的执行结果如下:从上面的结果可以看出,线程1和线程2都在等待对方释放锁,从而造成了死锁问题。死锁的成因通过上面的例子,我们可以得出结论,需要满足以下四个条件才能产生死锁:互斥条件:指的是互斥的操作单元(进程、线程或协程)到分配的资源,也就是说一定的锁在一段时间内一个资源只能被一个计算单元占用。请求和保持条件:指操作单元至少保留了一个资源,但又提出新的资源请求,该资源已被其他操作单元占用。坚持,稍等。不可剥夺条件:指计算单元获得的资源,在用完之前不能被剥夺。循环等待条件:发生死锁时,必然存在计算单元和资源的循环链,即计算单元在等待另一个计算单元占用的资源,而另一方在等待自己占用的资源,导致循环等待案例。只有同时满足以上4个条件,才会出现死锁问题。死锁排查如果程序出现死锁问题,可以通过以下4种解决方案中的任意一种进行分析排查。方案一:jstack在我们使用jstack之前,我们需要通过jps获取到运行程序的进程ID。使用方法如下:“jps-l”可以查询本机所有Java程序。jps(JavaVirtualMachineProcessStatusTool)是一个Java提供的显示当前所有Java进程的pid的命令,适用于在linux/unix/windows平台上查看当前Java进程的一些简单情况,“-l”为用于输出进程pid和运行程序的全路径名(包名和类名)。我们有了进程ID(PID)之后,就可以通过“jstack-lPID”来查找死锁问题了,如下图所示:jstack用于生成Java虚拟机当前时刻的线程快照,“-l”表示长列表(long),打印关于锁的附加信息。PS:可以使用jstack-help查看更多命令说明。方案二:jconsole使用jconsole需要打开JDK的bin目录,找到jconsole双击打开,如下图:然后选择要调试的程序,如下图:然后点击连接进入,选择“不安全连接”进入监控首页,如下图:然后切换到“线程”模块,点击“检测死锁”按钮,如下图:过段时间会检测到死锁的相关信息,如下图:方案三:jvisualvmjvisualvm也在JDK的bin目录下,同样是双击打开:几秒后,所有本地Java程序都会出现在jvisualvm中,如下图:双击选择要调试的程序:单机鼠标进入“线程”模块,如下图:从中可以看出上图,当我们切换到线程栏时,会直接显示死锁信息,然后点击“ThreadDump”生成死锁的详细信息,如下图:解决方案4:jmcjmc是的缩写OracleJavaMissionControl,这是一套用于管理、监视、分析和排除Java程序故障的工具。同样在JDK的bin目录下,同样是双击启动,如下图:jmc主页信息如下:选择要检查的程序后,右键“StartJMXConsole”可以查看程序的详细信息,如下图:然后点击“Thread”,勾选“DeadlockDetection”,可以找到死锁和死锁的详细信息,如下图:总结死锁是因为两个或者多个计算单元互相等待对方停止Execution获取系统资源,但是任何一方都没有提前退出,所以就出现了死锁。死锁排查工具有四种:jstackjconsolejvisualvmjmc考虑到易用性和性能,推荐使用jconsole或者jvisualvm排查死锁。参考&致谢blog.csdn.net/u010648555/article/details/80721815cnblogs.com/cxuanBlog/p/13202898.htmlzh.wikipedia.org/zh-hans/Deadlock并发原创文章推荐线程的4种创建方法和详解!Java中的用户线程和守护线程有这么大的区别吗?深入理解ThreadPool线程池的7种创建方式,强烈推荐大家使用……池化技术到底有多牛?看到线程和线程池的对比,惊呆了!并发中的线程同步和locksynchronized锁this和class的区别!volatile和synchronized的区别轻量级锁就一定比重量级锁快吗?这样终止线程会导致服务宕机?SimpleDateFormat线程不安全的5个解决方案!ThreadLocal不好用?这就是你没用的原因!ThreadLocal内存溢出代码演示及原因分析!信号量告白:限流器我用对了!CountDownLatch:别招手了,等大家再次加入我们!CyclicBarrier:当所有人都准备好后,司机就可以发动汽车了!synchronized优化方法的锁扩展机制!synchronized中的4个优化,你知道几个?ReentrantLock的4个坑!图解:为什么非公平锁性能更高?关注公众号“Java中文社区”,查看更多有趣的Java并发知识文章。