【工作随手记】deaklock排查
生产环境当中还没真正遇到过死锁的问题。有些疑似死锁的问题,后来经过排查也只是其它问题导致的。所以通过jstack到底怎样排查死锁问题有点疏忽了。这里作个记录。
模拟一个死锁
顺便复习一下。
死锁的产生有四个必要的条件
互斥使用,即当资源被一个线程占用时,别的线程不能使用
不可抢占,资源请求者不能强制从资源占有者手中抢夺资源,资源只能由占有者主动释放
请求和保持,当资源请求者在请求其他资源的同时保持对原因资源的占有
循环等待,多个线程存在环路的锁依赖关系而永远等待下去,例如T1占有T2的资源,T2占有T3的资源,T3占有T1的资源,这种情况可能会形成一个等待环路
对于死锁产生的四个条件只要能破坏其中一条即可让死锁消失,但是条件一是基础,不能被破坏。
模拟一个死锁。
private static String lock1 = "lock1";
private static String lock2 = "lock2";
public static void main(String[] args) {
Runnable r1 = new Runnable() {
@Override
public void run() {
synchronized (lock1){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + " 锁住了lock1");
synchronized (lock2){
System.out.println(Thread.currentThread() + " 锁住了lock2");
}
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
synchronized (lock2){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + " 锁住了lock2");
synchronized (lock1){
System.out.println(Thread.currentThread() + " 锁住了lock1");
}
}
}
};
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(r1);
executorService.submit(r2);
}
执行输出
Thread[pool-1-thread-1,5,main] 锁住了lock1
Thread[pool-1-thread-2,5,main] 锁住了lock2
后面一直卡住,通过idea查看堆栈信息可以看到,两个线程互相一直在等待对方释放锁。
"pool-1-thread-2" #13 prio=5 os_prio=0 tid=0x000000001ebc6000 nid=0xcf950 waiting for monitor entry [0x00000000207fe000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.nyp.test.DeadlockTest$2.run(DeadlockTest.java:49)
- waiting to lock <0x000000076b19de70> (a java.lang.String)
- locked <0x000000076b19dea8> (a java.lang.String)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
"pool-1-thread-1" #12 prio=5 os_prio=0 tid=0x000000001ebc5000 nid=0xcfa20 waiting for monitor entry [0x00000000206ff000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.nyp.test.DeadlockTest$1.run(DeadlockTest.java:31)
- waiting to lock <0x000000076b19dea8> (a java.lang.String)
- locked <0x000000076b19de70> (a java.lang.String)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
通过idea我们很方便的观察到了两个线程在等待对方释放锁,而且通过观察其它的堆栈信息我们也能方便的知道,两个线程也分别锁住了对方想要申请的锁,因此造成了死锁。
但是在生产环境中,通过jstack会打印出一大堆线程的信息,而且只有有并发环境必然会上锁,堆栈信息当中必然会出现waiting for monitor``waiting on condition``locked等信息,这并不是死锁的完全充要条件。
将代码放到生产环境。通过jstack pid命令,可以看到会出现明确的deadlock的信息。
Found one Java-level deadlock:
"pool-4-thread-2":
waiting to lock monitor 0x00007f0c24026408 (object 0x00000005d0e7a708, a java.lang.String),
which is held by "pool-4-thread-1"
"pool-4-thread-1":
waiting to lock monitor 0x00007f0c24025c78 (object 0x00000005d0e7a740, a java.lang.String),
which is held by "pool-4-thread-2"
Java stack information for the threads listed above:
"pool-4-thread-2":
at com.alpha.data.util.DeadlockTest$2.run(DeadlockTest.java:49)
- waiting to lock <0x00000005d0e7a708> (a java.lang.String)
- locked <0x00000005d0e7a740> (a java.lang.String)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
"pool-4-thread-1":
at com.alpha.data.util.DeadlockTest$1.run(DeadlockTest.java:31)- waiting to lock <0x00000005d0e7a740> (a java.lang.String)
- locked <0x00000005d0e7a708> (a java.lang.String)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
Found 1 deadlock.
也就是在生产环境中,通过jstack排查死锁问题时 ,只需要盯着deadlock字样即可,如果有死锁会明显的提示出产生死锁的代码所在。否则,便是没有死锁。
顺便复习一下通过jstack排查cpu占用高的问题
1.通过top命令找到cpu占用高的应用程序进程
2.通过top -H -p pid查看该应用中占用CPU高的线程。
3.通过printf "%x\n" pid 将线程高的线程号转为十六进制。
4.通过jstack过滤该十六进制的关键信息。jstack pid | grep 十六进制 -c 10

这样就可以看到占用CPU高的代码位置。
总结:就是先查到占用高的应用和具体的线程,然后根据线程到堆积信息查找即可。
不过堆栈信息非十进制,需提前把线程号转为十六进制。
【工作随手记】deaklock排查的更多相关文章
- K60平台智能车开发工作随手记
(图片仅为示例,并不一定固定为这种造型) 第十二届全国大学生智能汽车竞赛有一个分项是光电四轮车的竞速(任务A),Seven她们组采购到的配件使用了freescale Crotex-M4内核的CPU,T ...
- 一次生产环境CPU占用高的排查
1. 项目背景 甲方是保密级别非常高的政府部门.所以我们全程拿不到任何测试数据,只能是自己模拟数据进行测试. 项目部署的时候,公司派了一人到甲方现场,在甲方客户全程监督下,进行部署,调试,导入数据等工 ...
- Java线上问题排查思路及Linux常用问题分析命令学习
前言 之前线上有过一两次OOM的问题,但是每次定位问题都有点手足无措的感觉,刚好利用星期天,以测试环境为模版来学习一下Linux常用的几个排查问题的命令. 也可以帮助自己在以后的工作中快速的排查线上问 ...
- Azure 虚拟机诊断设置问题排查
Azure 为用户提供了可以自己配置的性能监控功能:Azure 诊断扩展.但是在具体配置中,经常会遇到各种各样的问题.不了解监控的工作机制常常给排查带来一定难度.这里我们整理了关于 Azure 虚拟机 ...
- traceroute排查网络故障 www.qq.com排查网络故障网络不通 先ping自己
网络不通 先ping自己 在ping网关 再ping外网 再ping别人的ip 背景需求 Linux 因为其强大的网络处理能力,被广泛用于网关(实例链接)和服务器(实例链接).实际工作中,快速排查这些 ...
- Oracle数据库ORA-12154: TNS: 无法解析指定的连接标识符详解
ORA-12154: TNS: 无法解析指定的连接标识符(转自http://www.cnblogs.com/psforever/p/3929064.html) 相信使用过Oracle数据库的人一定碰到 ...
- webapp调试工具weinre的使用
在设计师与前端开发人员的努力下,一个WebApp出炉了,可是测试人员说了一堆的问题:某某机型下页面表现不一致,某某系统下页面如何如何,某某 系统浏览器下页面怎么怎么滴.看着满满的测试汇总文档,我们曾经 ...
- Oracle学习之常见错误整理
一.ORA-12154: TNS: 无法解析指定的连接标识符 在程序中连接Oracle数据库的方式与其他常用数据库,如:MySql,Sql Server不同,这些数据库可以通过直接指定IP的方式连接, ...
- kubernetes1.4 基础篇:Learn Kubernetes 1.4 by 6 steps
本教程受Kubernetes官方最新更新的文档所触发,之所以没有做单纯的翻译是因为如下几个原因: Kubernetes官方此教程基于minikube,个人对minikube可能有偏见,觉得像玩具. M ...
- python scrapy 入门,10分钟完成一个爬虫
在TensorFlow热起来之前,很多人学习python的原因是因为想写爬虫.的确,有着丰富第三方库的python很适合干这种工作. Scrapy是一个易学易用的爬虫框架,尽管因为互联网多变的复杂性仍 ...
随机推荐
- ANOMALY: use of REX.w is meaningless (default operand size is 64)
1.打开注册机:win+ R 输入regedit2.找到目录:计算机\HKEY_LOCAL_MACHINE\SOFTWARE\TEC\Ocular.3\agent\config 并添加值3.新增项 ...
- adb命令启动报错Error: unknown command '-start'怎么办
大家好,每天记录小问题.水滴石穿. 今天介绍一个从0开始启动app应用的app命令 adb shell am -start -w -n 包名/启动名 第一次运行时报错 怎么办呢, 这边使用的是雷电模拟 ...
- Spring事务的底层原理
1. 划分处理单元--IOC 由于spring解决的问题是对单个数据库进行局部事务处理的,具体的实现首相用spring 中的IOC划分了事务处理单元.并且将对事务的各种配置放到了ioc容器中(设置事务 ...
- 续集来了!我让 GPT-4 用 Laf 三分钟写了个完整的待办事项 App
书接前文,上篇文章我们教大家如何三分钟时间用 Laf 实现一个自己的 ChatGPT. 一觉醒来,GPT-4 已经发布了! GPT-4 实现了真正的多模态,可以把纸笔画的原型直接写出网页代码.读论文时 ...
- 酷狗的kgma文件,居然包含两个版本
酷狗的kgma文件,居然可以包含两个版本,看看两首歌的歌曲信息. 歌曲信息中可以看到两首格式.时间.大小都是不一样的,但是这两首歌曲的本地文件地址都指向 F:\KuGou\KugouMusic\丸子呦 ...
- STM32F407 学习 (0) 各种外设功能 (中)
十.高级定时器 1.重复计数器 如果我们设置重复计数器寄存器 RCR 的值为 N,那么更新事件将在定时器发生 N+1 次上溢或下溢时发生.重复计数器的特性,在控制生成 PWM 信号时很有用. 2. ...
- java开发技术栈如何选型
前言 2023泰山景区门票免费政策是从1月21日到3月31,今天4.1起不再免费啦,泰山的人.山和系统终于平安的渡劫过去! 洪峰时疯狂的抢票.各类攻击,分销MT两次凌晨抗洪事件,我及其我的团队又一次得 ...
- k8s集群进行删除并添加node节点
在已建立好的k8s集群中删除节点后,进行添加新的节点,可参考用于添加全新node节点,若新的node需要安装docker和k8s基础组件. 建立集群可以参考曾经的文章:CentOS8 搭建Kubern ...
- Kubernetes(K8S)内核优化常用参数详解
net.ipv4.tcp_keepalive_time=600 net.ipv4.tcp_keepalive_intvl=30 net.ipv4.tcp_keepalive_probes=10 net ...
- 异步注解@Async使用及其部分调优
对于spring异步注解@Async的使用: 对于异步方法调用,从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调用该方法.调用者将在调用时立即返回,方法的实际执行将提 ...