生产环境当中还没真正遇到过死锁的问题。有些疑似死锁的问题,后来经过排查也只是其它问题导致的。所以通过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排查的更多相关文章

  1. K60平台智能车开发工作随手记

    (图片仅为示例,并不一定固定为这种造型) 第十二届全国大学生智能汽车竞赛有一个分项是光电四轮车的竞速(任务A),Seven她们组采购到的配件使用了freescale Crotex-M4内核的CPU,T ...

  2. 一次生产环境CPU占用高的排查

    1. 项目背景 甲方是保密级别非常高的政府部门.所以我们全程拿不到任何测试数据,只能是自己模拟数据进行测试. 项目部署的时候,公司派了一人到甲方现场,在甲方客户全程监督下,进行部署,调试,导入数据等工 ...

  3. Java线上问题排查思路及Linux常用问题分析命令学习

    前言 之前线上有过一两次OOM的问题,但是每次定位问题都有点手足无措的感觉,刚好利用星期天,以测试环境为模版来学习一下Linux常用的几个排查问题的命令. 也可以帮助自己在以后的工作中快速的排查线上问 ...

  4. Azure 虚拟机诊断设置问题排查

    Azure 为用户提供了可以自己配置的性能监控功能:Azure 诊断扩展.但是在具体配置中,经常会遇到各种各样的问题.不了解监控的工作机制常常给排查带来一定难度.这里我们整理了关于 Azure 虚拟机 ...

  5. traceroute排查网络故障 www.qq.com排查网络故障网络不通 先ping自己

    网络不通 先ping自己 在ping网关 再ping外网 再ping别人的ip 背景需求 Linux 因为其强大的网络处理能力,被广泛用于网关(实例链接)和服务器(实例链接).实际工作中,快速排查这些 ...

  6. Oracle数据库ORA-12154: TNS: 无法解析指定的连接标识符详解

    ORA-12154: TNS: 无法解析指定的连接标识符(转自http://www.cnblogs.com/psforever/p/3929064.html) 相信使用过Oracle数据库的人一定碰到 ...

  7. webapp调试工具weinre的使用

    在设计师与前端开发人员的努力下,一个WebApp出炉了,可是测试人员说了一堆的问题:某某机型下页面表现不一致,某某系统下页面如何如何,某某 系统浏览器下页面怎么怎么滴.看着满满的测试汇总文档,我们曾经 ...

  8. Oracle学习之常见错误整理

    一.ORA-12154: TNS: 无法解析指定的连接标识符 在程序中连接Oracle数据库的方式与其他常用数据库,如:MySql,Sql Server不同,这些数据库可以通过直接指定IP的方式连接, ...

  9. kubernetes1.4 基础篇:Learn Kubernetes 1.4 by 6 steps

    本教程受Kubernetes官方最新更新的文档所触发,之所以没有做单纯的翻译是因为如下几个原因: Kubernetes官方此教程基于minikube,个人对minikube可能有偏见,觉得像玩具. M ...

  10. python scrapy 入门,10分钟完成一个爬虫

    在TensorFlow热起来之前,很多人学习python的原因是因为想写爬虫.的确,有着丰富第三方库的python很适合干这种工作. Scrapy是一个易学易用的爬虫框架,尽管因为互联网多变的复杂性仍 ...

随机推荐

  1. 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.新增项 ...

  2. adb命令启动报错Error: unknown command '-start'怎么办

    大家好,每天记录小问题.水滴石穿. 今天介绍一个从0开始启动app应用的app命令 adb shell am -start -w -n 包名/启动名 第一次运行时报错 怎么办呢, 这边使用的是雷电模拟 ...

  3. Spring事务的底层原理

    1. 划分处理单元--IOC 由于spring解决的问题是对单个数据库进行局部事务处理的,具体的实现首相用spring 中的IOC划分了事务处理单元.并且将对事务的各种配置放到了ioc容器中(设置事务 ...

  4. 续集来了!我让 GPT-4 用 Laf 三分钟写了个完整的待办事项 App

    书接前文,上篇文章我们教大家如何三分钟时间用 Laf 实现一个自己的 ChatGPT. 一觉醒来,GPT-4 已经发布了! GPT-4 实现了真正的多模态,可以把纸笔画的原型直接写出网页代码.读论文时 ...

  5. 酷狗的kgma文件,居然包含两个版本

    酷狗的kgma文件,居然可以包含两个版本,看看两首歌的歌曲信息. 歌曲信息中可以看到两首格式.时间.大小都是不一样的,但是这两首歌曲的本地文件地址都指向 F:\KuGou\KugouMusic\丸子呦 ...

  6. STM32F407 学习 (0) 各种外设功能 (中)

    十.高级定时器 1.重复计数器   如果我们设置重复计数器寄存器 RCR 的值为 N,那么更新事件将在定时器发生 N+1 次上溢或下溢时发生.重复计数器的特性,在控制生成 PWM 信号时很有用. 2. ...

  7. java开发技术栈如何选型

    前言 2023泰山景区门票免费政策是从1月21日到3月31,今天4.1起不再免费啦,泰山的人.山和系统终于平安的渡劫过去! 洪峰时疯狂的抢票.各类攻击,分销MT两次凌晨抗洪事件,我及其我的团队又一次得 ...

  8. k8s集群进行删除并添加node节点

    在已建立好的k8s集群中删除节点后,进行添加新的节点,可参考用于添加全新node节点,若新的node需要安装docker和k8s基础组件. 建立集群可以参考曾经的文章:CentOS8 搭建Kubern ...

  9. Kubernetes(K8S)内核优化常用参数详解

    net.ipv4.tcp_keepalive_time=600 net.ipv4.tcp_keepalive_intvl=30 net.ipv4.tcp_keepalive_probes=10 net ...

  10. 异步注解@Async使用及其部分调优

    对于spring异步注解@Async的使用: 对于异步方法调用,从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调用该方法.调用者将在调用时立即返回,方法的实际执行将提 ...