3、通过 jstack PID 查看进程信息

文章插图
接下来的信息:在jstack输出的信息中最后出现了死锁提示,提示显示在DeadThread.java文件的第39行和23行,那你去排查代码就可以啦

文章插图
方式2:通过jconsole工具这个工具在查看JVM内存时也是可以使用的,它是JDK中携带官方提供的工具,无需下载第三方插件即可使用
1、打开 jconsole 工具,在命令行输入jconsole即可开启,箭头右侧就是该工具启动页

文章插图
2、选择对应的Java进程查看信息,双击选中PID为128的Java进程

文章插图
3、选中线程,点击下方检查死锁按钮

文章插图
4、死锁检测结果,也会将死锁的信息展示出开【右侧信息需要双击左侧线程名才会展示出来】

文章插图
如何避免死锁这里说的避免死锁,其实是在生产环境中也就是项目上线运行不要出现死锁,不然又要被喊过去加班了,上边说了死锁产生的四个条件,只要我们将这四个条件中的任意一个破坏就不会产生死锁 。
- 禁止一个线程同时持有多把锁
- 具备相同的加锁顺序
- 设置锁超时
- 死锁检测
package com.tianzhen.thread;public class DeadThread {// 工作锁private static Object work = new Object();// 工作经验锁private static Object workExperience = new Object();public static void main(String[] args) {// 企业线程new Thread(() -> {// 工作synchronized (work) {System.out.println(Thread.currentThread().getName() + "来吧!加入我们,有无经验都可");// 工作经验synchronized (workExperience) {System.out.println(Thread.currentThread().getName() + "感谢你的加入,为我们注入新鲜血液");}}},"企业线程:").start();// 员工线程new Thread(() -> {// 先获取工作机会synchronized (work) {System.out.println(Thread.currentThread().getName() + "我没有工作经验");// 有工作经验synchronized (workExperience) {System.out.println(Thread.currentThread().getName() + "通过工作获得了工作经验");}}},"面试者线程:").start();}}运行结果:
文章插图
此时就不会出现死锁,当企业线程运行占用work锁,这是如果发生线程切换,面试者也是要获取work锁,此时发现获取不到,就会进入阻塞,CPU放弃执行转而执行企业线程,此时企业线程获取workExperience锁,因为加锁顺序相同,此锁必然没有被比别的线程占用可以获得,继续执行,但是此时就无法实现交替执行,如果需要交替执行则需要使用线程通信实现,后边会安排此部分内容
方案2:设置超时因为 synchronized 不会自动释放,无法设置超时时间,此方案需要通过Lock接口实现,改接口在Java并发编程合集的《Java线程安全问题和解决方案》一文中有详细介绍
- 通过tryLock尝试获取锁,如果获取不到就立即失败,不进入阻塞,你也可以调用tryLock(long time, TimeUnit unit)方法,设置获取所得超时时间,如果指定的时间没有获取到则继续运行
- 在finally中记得通过unlock方法释放锁,如果不释放锁,就会一直持有,陷入死锁
package com.tianzhen.thread;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class DeadThread {// 工作锁private static Lock work = new ReentrantLock();// 工作经验锁private static Lock workExperience = new ReentrantLock();public static void main(String[] args) {// 企业线程new Thread(() -> {// 工作if (workExperience.tryLock()) {try {System.out.println(Thread.currentThread().getName() + "没有工作经验,立即失败!");// 工作锁if (work.tryLock()) {try {System.out.println(Thread.currentThread().getName() + "技术不行,立即失败!");} finally {work.unlock();}}System.out.println(Thread.currentThread().getName() + "有工作经验,通过面试,欢迎加入我们!");} finally {workExperience.unlock();}}}, "企业线程:").start();// 员工线程new Thread(() -> {if (work.tryLock()) {try {System.out.println(Thread.currentThread().getName() + "我需要工作,才能有工作经验!");// 工作锁if (workExperience.tryLock()) {try {System.out.println(Thread.currentThread().getName() + "没有工作经验,告辞告辞!");} finally {workExperience.unlock();}}System.out.println(Thread.currentThread().getName() + "有工作经验,获取工作!");} finally {work.unlock();}}}, "面试者线程:").start();}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 怎么看内存条频率是3200还是2666 怎么看内存条频率
- sd内存条?现在SD内存卡最大是多少G?
- 内存卡数据恢复软件免费 内存卡数据恢复软件
- 凯迪拉克流媒体内存卡;什么是流媒体音乐
- 怎样清理电脑内存垃圾 怎样清理电脑内存
- 一招修复内存不能read桌面不显示 应用程序错误
- 相机内存卡数据恢复软件免费版 相机内存卡数据恢复
- 长月烬明|首播6集收视率飙升,评分剑指8.8,强大的演员阵容十分令观众期待
- 32位系统内存限制解决 32位系统内存
- 360手机病毒清理 清理一下内存
