• 使用JDK自带的工具jstack找出造成运行程序死锁的原因


    Java多线程编程也是Java面试中经常考察的内容。刚接触Java多线程编程的朋友们,可能会不慎写出一些会导致死锁(deadlock)的应用出来。如何分析造成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:

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

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

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

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

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

  • 相关阅读:
    如何设置范围,使透视数据源记录可以自适应地改变
    Atitit..文件上传组件选择and最佳实践的总结(2)----HTTP
    AIDL(1)
    最好的年龄减肥
    2012在数据库技术会议上的讲话PPT打包
    左右 Java 于 finally 深度分析语句块
    R0-R37它是Arm 寄存器,那是,CPU内部。和GPIO注册所有外设。换句话说,要是arm的cpu,它包含了其他芯片公司将有R0-R37,和GPIO寄存器只有一个特定的芯片。
    使用方便 正则表达式grep,sed,awk(一)
    经验36--C#无名(大事,物...)
    IOS 图片压缩
  • 原文地址:https://www.cnblogs.com/sap-jerry/p/9818882.html
Copyright © 2020-2023  润新知