java死锁排查

锁是个非常有用的工具,运用场景非常多,因为其使用起来非常简单,而且易于理解。但同时它也会带来一些困扰,那就是可能会引起死锁,一旦产生死锁,会造成系统功能不可用。让我们先来看一段代码,这段代码会引起死锁,线程t1和t2互相等待对方释放锁。

package chapter1;

public class DeadLockDemo {

    /** A锁 */
    private static String A = "A";
    /** B锁 */
    private static String B = "B";

    public static void main(String[] args) {
        new DeadLockDemo().deadLock();
    }

    private void deadLock() {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                synchronized (A) {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (B) {
                        System.out.println("1");
                    }
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                synchronized (B) {
                    synchronized (A) {
                        System.out.println("2");
                    }
                }
            }
        });
        t1.start();
        t2.start();
    }

}

admindeMacBook-Pro-108:~ hzjdemac$ ps aux | grep DeadLockDemo
hzjdemac         73794   0.0  0.0  4279032    888 s004  S+    5:56下午   0:00.00 grep DeadLockDemo
hzjdemac         72373   0.0  0.1 10102764  19812   ??  S     5:19下午   0:02.35 /Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/lib/tools.jar:/Users/hzjdemac/IdeaProjects/java-learning/target/classes:/Users/hzjdemac/.m2/repository/com/alibaba/fastjson/1.2.29/fastjson-1.2.29.jar:/Users/hzjdemac/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar chapter1.DeadLockDemo
admindeMacBook-Pro-108:~ hzjdemac$ jstack 72373
2019-02-24 17:57:01
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.101-b13 mixed mode):

"Attach Listener" #13 daemon prio=9 os_prio=31 tid=0x00007fa2a905d800 nid=0x1107 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #12 prio=5 os_prio=31 tid=0x00007fa2ab005800 nid=0x2503 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #11 prio=5 os_prio=31 tid=0x00007fa2ab079800 nid=0xa803 waiting for monitor entry [0x000070000546b000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at chapter1.DeadLockDemo$2.run(DeadLockDemo.java:38)
    - waiting to lock <0x000000076abaccd8> (a java.lang.String)
    - locked <0x000000076abacd08> (a java.lang.String)
    at java.lang.Thread.run(Thread.java:745)

"Thread-0" #10 prio=5 os_prio=31 tid=0x00007fa2ab07d800 nid=0xa903 waiting for monitor entry [0x0000700005368000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at chapter1.DeadLockDemo$1.run(DeadLockDemo.java:28)
    - waiting to lock <0x000000076abacd08> (a java.lang.String)
    - locked <0x000000076abaccd8> (a java.lang.String)
    at java.lang.Thread.run(Thread.java:745)
  ...
java死锁排查_第1张图片
image.png

这段代码只是演示死锁的场景,在现实中你可能很难会写出这样的代码。但是一些更为复杂的场景中你可能会遇到这样的问题,比如t1拿到锁之后,因为一些异常情况没有释放锁,比如死循环。又或者是t1拿到一个数据库锁,释放锁的时候抛了异常,没释放掉。

现在我们介绍下如何避免死锁的几个常见方法。
避免一个线程同时获取多个锁。
避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
尝试使用定时锁,使用tryLock(timeout)来替代使用内部锁机制。
对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败。

你可能感兴趣的:(java死锁排查)