【工作随手记】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是一个易学易用的爬虫框架,尽管因为互联网多变的复杂性仍 ...
随机推荐
- Keil 报错解决方法:Cannot link object xxx.o as its attributes are incompatile with the image attributes
链接其他人的lib库时报错:Cannot link object xxx.o as its attributes are incompatile with the image attributes 解 ...
- 关于前端JS的一些常用方法和知识
关于前端数据存储目前只解释有三种:cookie.localStorage.sessionStorage cookie解释:只针对当前session(会话)有效,关闭标签页即失效使用: 1 var ck ...
- Javaweb基础复习------Filter相关应用+登录验证案例的使用
Filter(过滤器) 基本步骤: 1.定义类,实现Filter接口,并重写其所有方法 2.配置Filter拦截资源的路径,在类上定义2 WebFilter注解(WebFilter配置的路径,是拦截资 ...
- 全网最详细中英文ChatGPT接口文档(三)30分钟快速入门ChatGPT——资源库
目录 Python library(Python库) Node.js library(Node.js库) Community libraries 社区图书馆 C# / .NET Crystal Go ...
- Hello, YOU -- 通过简单的 hello_test.go 程序理解并学会编写测试
Hello, YOU 书接上文上篇文章中,我们尝试编写了hello word 函数以及第一个测试 hello_test package main import "fmt" func ...
- 数据库相关知识点整理,助力拿到心仪的offer
1. 数据库的事务 1.1 什么是数据库事务? 事务是指一组逻辑上相关的操作,这些操作要么全部完成,要么全部不完成. 事务是数据库管理系统执行过程中的一个逻辑工作单位,是用户定义的一个操作序列,这些操 ...
- 在Vue3+TypeScript 前端项目中使用事件总线Mitt
事件总线Mitt使用非常简单,本篇随笔介绍在Vue3+TypeScript 前端项目中使用的一些场景和思路.我们在Vue 的项目中,经常会通过emits 触发事件来通知组件或者页面进行相应的处理,不过 ...
- Mac连接Win的方法
前言 我们都知道,Mac和Win还是非常不一样的,作为Macdows双修选手,我今天给大家介绍一些从Mac连接Win的方法. Win的RDP 由于Win默认未安装ssh,我们最常使用的连接方式则是使用 ...
- 剑指 offer 第 2 天
第 2 天 链表(简单) 剑指 Offer 06. 从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入:head = [1,3,2] 输出:[2, ...
- TypeScript 学习笔记 — 基于对象操作的内置类型的使用(十二)
目录 1.Partial 转化可选属性 (?) 2.Required 转化必填属性 (-?) 3.Readonly 转化仅读属性 (readonly) Mutate(非内置,与 Readonly 相对 ...