jstack分析多线程死锁,来吧老铁们
本文源自 公-众-号 IT老哥 的分享
IT老哥,一个在大厂做高级Java开发的程序员,每天分享技术干货文章
前言
死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
1、模拟死锁
public class DeadLockTest {
public static void main(String[] args){
A a = new A();
B b = new B();
// a和b互相引用
a.next = b;
b.next = a;
// 启动a b两个线程
new Thread(a,"aThread").start();
new Thread(b,"bThread").start();
}
}
class A extends T implements Runnable {
T next;
public synchronized void invoke() {
System.out.println("当前线程:" + Thread.currentThread().getName()
+ " | 进入了" + this.getClass().getSimpleName() + " 获取到资源 | 准备调用:"
+ next.getClass().getSimpleName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
next.invoke();
}
@Override
public void run() {
invoke();
}
}
class B extends T implements Runnable {
T next;
public synchronized void invoke() {
System.out.println("当前线程:" + Thread.currentThread().getName()
+ " | 进入了" + this.getClass().getSimpleName() + " 获取到资源 | 准备调用:"
+ next.getClass().getSimpleName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
next.invoke();
}
@Override
public void run() {
invoke();
}
}
class T {
public synchronized void invoke(){ }
}
上面的代码也很简单,就是A对象持有
B对象的引用
,B对象持有
A对象的引用
。
在线程a进入到invoke
方法时锁住
了A对象,线程b也进入到invoke方法锁住了B对象。
线程a再调用
B对象的invoke
方法去试图锁住B对象时,发现B对象已经被锁住了,需要等待,同理b线程也是如此。
就导致了两个线程相互等待对方释放锁。有点绕,如果不明白,好好品下。
咱们运行下上面的代码,看下结果:
当前线程:aThread | 进入了A 获取到资源 | 准备调用:B
当前线程:bThread | 进入了B 获取到资源 | 准备调用:A
2、查找进程日志
我们使用jps查找进程,再用jstack dump线程日志信息
dump的时候忘记加磁盘标识,结果dump的文件到C:UsersAdministrator这个目录里面去了
3、分析
下面我们看看日志里面是怎么记录的,首先,我们全文搜索【deadlock】关键字,如下图:
上图展示了bThread和aThread发生了死锁,具体是哪块的代码还不清楚,咱们根据A对象0x000000078bb84c68继续往下搜索
现在咱们就很清楚死锁的代码所在了,剩下的就是优化代码了。
4、总结
一般来说,线程的日志是非常大,不可能一眼就能看出问题的所在,现在我们重点来说排查的思路:
首先就要找关键字,比如:
- deadlock:表示有死锁。
- Waiting on condition:等待某个资源或条件发生来唤醒自己。
- Blocked:阻塞。
- Waiting on monitor entry:在等待获取锁。
找到这些关键字,再找到具体的线程进行分析,最后根据线程死锁的执行的方法,去查看代码。
结束语
本篇到此把jstack命令介绍完了,下一篇将使用jmap的分析内存泄漏。
云服务器,云硬盘,数据库(包括MySQL、Redis、MongoDB、SQL Server),CDN流量包,短信流量包,cos资源包,消息队列ckafka,点播资源包,实时音视频套餐,网站管家(WAF),大禹BGP高防(包含高防包及高防IP),云解析,SSL证书,手游安全MTP,移动应用安全、 云直播等等。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JWT登录信息加密
- 我画了近百张图来理解红黑树
- SpringBoot之API--Swagger2接口文档管理
- 索引失效原理,终于有人讲明白了
- 你真了解你的系统吗?它要崩溃了
- 伸手党的容器镜像加固流程
- 前端模块化开发--React框架(四):高级应用(redux)
- Tomcat性能优化,学会薪水翻倍
- 前端模块化开发--React框架(三):应用进阶(react-router4&&antd框架)
- boost asio通信
- 前端模块化开发--React框架(二):脚手架&&网络请求框架
- Dubbo系列笔记之服务引用过程,不服不行
- 人人都能看懂的鸿蒙 “JS 小程序” 数据绑定原理
- Xcode12适配The linked library is missing one or more architectures required by this target问题
- [译] VueJS 中更好的组件组合方式