栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

用jstack找死锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

用jstack找死锁

java死锁主要依靠jstack命令来查找。

检测jstack

先配置好jdk环境变量,打开一个终端命令行,输入jstack回车。如果看到如下的字样,说明jstack是可用的。

Usage:
    jstack [-l][-e] 
 (to connect to running process)

Options:
    -l  long listing. Prints additional information about locks
    -e  extended listing. Prints additional information about threads
    -? -h --help -help to print this help message

死锁程序

用下面程序模拟死锁。
一个线程先拿锁1,然后拿锁2,另外一个线程先拿锁2,再拿锁1。

public class Main {

    public static final Object lock1 = new Object();
    public static final Object lock2 = new Object();
    public static void main(String[] args) {
 new Thread(
  () -> {
      synchronized (lock1) {
   try {
Thread.sleep(3000);
synchronized (lock2) {
    System.out.println("thread1");
}
   } catch (InterruptedException e) {
e.printStackTrace();
   }
      }
  }, "thread1").start();

 new Thread(
  () -> {
      synchronized (lock2) {
   try {
Thread.sleep(3000);
synchronized (lock1) {
    System.out.println("thread2");
}
   } catch (InterruptedException e) {
e.printStackTrace();
   }
      }
  }, "thread2").start();
    }
}

利用jstack检测死锁

运行好程序以后,打开终端命令行,输入

jps 

我们可以看到我们的类名Main

4080 Jps
4079 Main

前面的数字4097是进程id。
继续输入jstack pid。例子中的pid是4079.

jstack 4079

直接看最后的输出,下面的注释是为了方便解读

### java层面的死锁
Found one Java-level deadlock:
=============================
### 线程名
"thread2":
### 等待的锁,和不释放锁的线程
  waiting to lock monitor 0x00007fc2d482d8a8 (object 0x000000076ac24330, a java.lang.Object),
  ### 锁被名字叫thread1的线程获取
  which is held by "thread1"
"thread1":
  waiting to lock monitor 0x00007fc2d482b018 (object 0x000000076ac24340, a java.lang.Object),
  which is held by "thread2"

### 代码堆栈,可以定位上面的代码输出
Java stack information for the threads listed above:
===================================================
"thread2":
	at com.company.Main.lambda$main$1(Main.java:31)
	- waiting to lock <0x000000076ac24330> (a java.lang.Object)
	- locked <0x000000076ac24340> (a java.lang.Object)
	at com.company.Main$$Lambda$2/2129789493.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)
"thread1":
	at com.company.Main.lambda$main$0(Main.java:17)
	- waiting to lock <0x000000076ac24340> (a java.lang.Object)
	- locked <0x000000076ac24330> (a java.lang.Object)
	at com.company.Main$$Lambda$1/1607521710.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)

### 死锁的个数
Found 1 deadlock.

根据上面的信息和堆栈,我们很快能确认死锁的代码的位置。而且可以发现锁的对象是java.lang.Object
下面是一段ReentrantLock死锁的代码,用上面的方式进行解读,找出死锁。

public class EnrtyLock {

    public static final ReentrantLock lock1 = new ReentrantLock();
    public static final ReentrantLock lock2 = new ReentrantLock();
    public static void main(String[] args) {
 // write your code here
 new Thread(
  () -> {
      lock1.lock();
      try {
   Thread.sleep(3000);
   lock2.lock();
   System.out.println("thread1");
   lock2.unlock();
      } catch (InterruptedException e) {
   e.printStackTrace();
      }
      lock1.unlock();
  }, "thread1").start();
 new Thread(
  () -> {
      lock2.lock();
      try {
   Thread.sleep(3000);
   lock1.lock();
   System.out.println("thread2");
   lock1.unlock();
      } catch (InterruptedException e) {
   e.printStackTrace();
      }
      lock2.unlock();
  }, "thread2").start();
    }

}


Found one Java-level deadlock:
=============================
"thread2":
  waiting for ownable synchronizer 0x000000076ac2a328, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "thread1"
"thread1":
  waiting for ownable synchronizer 0x000000076ac2a358, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "thread2"


发现锁的对象变成了ReentrantLock。证明jstack可以满足java的关键字以及基于aqs实现的锁。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号