【工作随手记】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是一个易学易用的爬虫框架,尽管因为互联网多变的复杂性仍 ...
随机推荐
- windows作业系统部署nfs服务
文件共享的需求是如何产生的? 据说当年美国和苏联冷战期间,双方都有摧毁对方的能力.而苏联 不怕死的性格让美国人多少有些害怕.美国当时害怕自己的军事指挥中心被苏联摧毁.于是,美国建立了阿帕网,并把自己的 ...
- LeetCode 周赛 338,贪心 / 埃氏筛 / 欧氏线性筛 / 前缀和 / 二分查找 / 拓扑排序
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 上周末是 LeetCode 第 338 场周赛,你参加了吗?这场周赛覆盖的知识点很多,第 ...
- react之点语法(利用函数组件)
index.js import React, { Component } from 'react' import MyCom from './MyCom'; export default class ...
- QML 界面切换的几种方法(带示例代码)
QML 界面切换的几种方法(带示例代码)
- 保持唯一性,请停止使用【python3 内置hash() 函数】
问题: 如图,用hash() 筛重时竟然出现了重复. 如下图: hash字符串时,同一窗口的是一致的,不同窗口结果竟然不同. 原因: python的字符串hash算法并不是直接遍历字符串每个字符去计算 ...
- Java19新特性
本文已经收录到Github仓库,该仓库包含计算机基础.Java基础.多线程.JVM.数据库.Redis.Spring.Mybatis.SpringMVC.SpringBoot.分布式.微服务.设计模式 ...
- Kubernetes 部署 MySQL 高可用读写分离
Kubernetes 部署 MySQL 高可用读写分离 简介: 在有状态应用中,MySQL是我们最常见也是最常用的.本文我们将实战部署一个一组多从的MySQL集群. 一.配置准备 configMap ...
- python注册热键方式
#!/usr/bin/env python3 import win32con import ctypes import ctypes.wintypes from threading import ...
- [网络]HTTPS下服务器与浏览器的通信:HTTPS背后的加密算法 | TLS := SSL [转载]
全文转载自: HTTPS背后的加密算法 - 博客园 1 概述: 基本原理/过程 当你在浏览器的地址栏上输入https开头的网址后,浏览器和服务器之间会在接下来的几百毫秒内进行大量的通信.InfoQ的这 ...
- Yii2批量插入数据
方法一 yii2一次插入多行数据 /** * @inheritdoc 批量添加 * @params $add array 添加数据 */ public function add_all($add) ...