多线程——检测、分析死锁工具(Jconsole \ Jstack)

8 篇文章 0 订阅
5 篇文章 0 订阅

死锁是多线程中的常见问题,经常与业务逻辑挂钩。如果逻辑复杂,检查起来会很困难。如果这时候有工具辅助,就方便多了。
这里介绍两个检查死锁的工具,都是jdk自带的,使用起来也非常简单。这两个工具分别是JconsoleJstack

首先来一段死锁代码:

public class TestThreadLock {	
	public void sync1() {
		synchronized(this) {
			try {
				System.out.println("test1");
				Thread.sleep(3000);// 休眠3秒,以让步给线程b的sync2方法,让其获取到类锁
				synchronized(TestThreadLock.class) {
					System.out.println("test11");
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void sync2() {
		synchronized(TestThreadLock.class) {
			try {
				System.out.println("test2");
				Thread.sleep(3000); // 休眠3秒,以让步给线程a的sync1方法,让其获取到对象锁
				synchronized(this) {
					System.out.println("test21");
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}	
	
	public static void main(String[] args) {
		TestThreadLock t = new TestThreadLock();
		
		Thread a = new Thread(new Runnable() {
			public void run() {
				t.sync1();
			}
		});
		a.setName("Thread-0");
		Thread b = new Thread(new Runnable() {
			public void run() {
				t.sync2();
			}
		});
		b.setName("Thread-1");
		
		a.start();
		b.start();
	}
}

代码解析:

  1. 线程a调用sync1方法,会先获取TestThreadLock的对象锁,然后休眠3秒;
  2. 趁着线程a休眠的时候,线程b运行,调用sync2方法,会获取TestThreadLock的类锁,然后也休眠3秒;
  3. 线程b休眠,就轮到线程a运行,此时线程a需要获取TestThreadLock的类锁,但是它被线程b占用着,线程a等待锁释放;
  4. 常规轮换到线程b执行,线程b需要TestThreadLock的对象锁,此时它被线程a占用着,线程b等待;
  5. 如此往复,线程a、b互相等待对方的锁,而自身占用的锁又必须获取到对方的锁之后才能释放,于是就形成了死锁。

接下来,我们就可以用工具来检查这个死锁。

Jconsole

Jconsole是JDK自带的图形化界面工具,打开cmd,输入jconsole,就可以打开工具了。
1、选择当前进程。
选择当前进程
2、在头部tab栏点击“线程”进入线程界面,点击最下方“检测死锁”进行检查。
进入线程界面,检测死锁
3、如果检查到死锁,这里就会把死锁的线程都列出来。
查看死锁的线程
如上,可以看出:
1、Thread-1线程在等待Thread.TestThreadLock@517bf122这个锁,而且可以看出来,这是个类锁;
2、Thread.TestThreadLock@517bf122这个锁的拥有者是Thread-0
在这里插入图片描述
3、当前Thread-1调用sync2方法,持有的锁是java.lang.Class@6d06d69c(对象锁)。
在这里插入图片描述
注:Jconsole工具除了可以检测死锁,还可以监控当前进程的内存情况、类情况等,是个很简单方便的工具,有兴趣的可以深入了解。


Jstack

Jstack是JDK自带的一种堆栈跟踪工具。
1、打开cmd,目录定位到java安装目录的bin目录下;
2、输入命令:jps
jps命令
3、查找当前进程对应的端口;(其中TestThreadLock就是当前进程)
当前进程TestThreadLock
4、输入命令:jstack -l [端口号]
jstack命令
5、得到当前线程的锁情况。(在打印出来的日志的最后)
死锁
如上,可以看到,最后的日志很清楚的展示了当前哪个线程获取了哪个锁,等待着哪个锁。以Thread-1线程为例:
1、Thread-1在等待着锁,且是类锁Thread.TestThreadLock
等待锁
2、Thread-1占用着锁,且是对象锁java.lang.Class for Thread.TestThreadLock(TestThreadLock对象);
占用锁
注:检测死锁,只是Jstack功能的一个体现,它主要是监测当前程序的堆栈情况。对于程序的运行监控和问题排查,是很有帮助的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值