【多线程】定位线程死锁

定位线程死锁的方式

  • jstack pid
  • 使用arthas

写一个死锁的小例子

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class DeadLockDemo {

    static Object o1 = new Object();
    static Object o2 = new Object();

    static ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 120, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));
    static CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException {

        executor.execute(() -> {
            synchronized (o1) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                synchronized (o2) {
                    System.out.println("线程1获得了两把锁");
                }
                countDownLatch.countDown();
            }
        });

        executor.execute(() -> {
            synchronized (o2) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                synchronized (o1) {
                    System.out.println("线程2获得了两把锁");
                }
                countDownLatch.countDown();
            }
        });
        countDownLatch.await();
    }
}

这个demo 启动后,线程就会死锁掉,
那怎样去查看是哪里发生了死锁呢?

方法一 jstack (推荐)

直接 jps 看一下要定位的进程的 Pid

然后 jstack pid > deadlock.log 打栈信息输出到一个文本中(当然,不输出也是可以的,个人喜欢)

然后在栈的后面,可以看到这么一段信息:

Java stack information for the threads listed above:
===================================================
"pool-1-thread-2":
	at com.carrot.thread.deadlock.DeadLockDemo.lambda$main$1(DeadLockDemo.java:50)
	- waiting to lock <0x000000076ac30978> (a java.lang.Object)
	- locked <0x000000076ac30988> (a java.lang.Object)
	at com.carrot.thread.deadlock.DeadLockDemo$$Lambda$2/1595428806.run(Unknown Source)
	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":
	at com.carrot.thread.deadlock.DeadLockDemo.lambda$main$0(DeadLockDemo.java:36)
	- waiting to lock <0x000000076ac30988> (a java.lang.Object)
	- locked <0x000000076ac30978> (a java.lang.Object)
	at com.carrot.thread.deadlock.DeadLockDemo$$Lambda$1/1329552164.run(Unknown Source)
	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)

Found 1 deadlock.

这里就很清楚地看到是哪些线程发生了死锁了。。。(当然这个是造的例子,定位起来也比较简单,具体情况以真实案例为准吧)

嗯...

方法二 使用arthas

这个就没什么好说的了, 进入 arthas 后
使用 thread -b

不过这个信息偏少,虽然也够了

[arthas@761]$ thread -b
"pool-1-thread-2" Id=12 BLOCKED on java.lang.Object@1c01e8b4 owned by "pool-1-thread-1" Id=11
    at com.carrot.thread.deadlock.DeadLockDemo.lambda$main$1(DeadLockDemo.java:53)
    -  blocked on java.lang.Object@1c01e8b4
    -  locked java.lang.Object@7bf02312 <---- but blocks 1 other threads!
    at com.carrot.thread.deadlock.DeadLockDemo$$Lambda$2/1595428806.run(Unknown Source)
    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)

    Number of locked synchronizers = 1
    - java.util.concurrent.ThreadPoolExecutor$Worker@3feba861

嗯,后续再补充吧。

posted @ 2023-02-21 21:17  aaacarrot  阅读(309)  评论(0编辑  收藏  举报