使用JDK自带的工具jstack找出形成运行程序死锁的缘由

Java多线程编程也是Java面试中常常考察的内容。刚接触Java多线程编程的朋友们,可能会不慎写出一些会致使死锁(deadlock)的应用出来。如何分析形成Java多线程的缘由呢?不少时候咱们在怀疑形成死锁的语句设置断点,单步调试,反而又不能重现了。这种现象很正常,由于我们单步调试和直接运行程序,代码执行的时序是不一样的,极可能没法知足死锁的触发条件。java

实际上,JDK已经给Java程序员提供了强大的死锁分析工具,可以直接分析一个正在运行的而且处于死锁状态的应用,并给出具体是哪一行Java代码引发的死锁。程序员

这篇文章就以一个例子来给你们演示如何使用这个JDK提供的标准工具。面试

这个工具叫jstack,就是JDK安装目录的bin文件夹下的一个执行文件。编程

咱们首先写一个会致使死锁的应用出来。多线程

public class DeadLockExample {
	public static void main(String[] args) {
		final String resource1 = "ABAP";
		final String resource2 = "Java";
		Thread t1 = new Thread() {
			public void run() {
				synchronized (resource1) {
					System.out.println("Thread 1: locked resource 1");
					try {
						Thread.sleep(100);
					}
					catch (Exception e) {
					}
					synchronized (resource2) {
						System.out.println("Thread 1: locked resource 2");
					}
				}
			}
		}
		;
		Thread t2 = new Thread() {
			public void run() {
				synchronized (resource2) {
					System.out.println("Thread 2: locked resource 2");
					try {
						Thread.sleep(100);
					}
					catch (Exception e) {
					}
					synchronized (resource1) {
						System.out.println("Thread 2: locked resource 1");
					}
				}
			}
		}
		;
		t1.start();
		t2.start();
	}
}

这个应用思路很简单,同时启动两个线程,分别锁住了resource1和resource2,而后休眠0.1秒,接着分别尝试去请求资源resource2和resource1。工具

执行应用,在控制台打印出下列输出后,进入死锁状态:命令行

Thread 1: locked resource 1线程

Thread 2: locked resource 2调试

使用命令行 jps -l -m找处处于死锁状态应用的进程id。从下图得知死锁进程为51476:code

而后使用命令行jstack 51476打印这个进程的运行栈信息。

我上图红色高亮出的 0x00000000d6f64988 和 0x00000000d6f649b8表明了代码中的两个资源“ABAP” 和“Java”。

jstack打印的输出很是清晰,显示了具体哪行Java代码试图去锁定哪个Java资源(下图的waiting to lock)可是没有成功, 而且将失败的缘由,即拥有当前请求资源的线程名称也打印了出来。

有了jstack,Java程序员不用对着冗长烧脑的多线程代码去左思右想了,JDK会自动把死锁缘由打印出来,太方便了。

要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

相关文章
相关标签/搜索