java死锁主要依靠jstack命令来查找。
检测jstack
先配置好jdk环境变量,打开一个终端命令行,输入jstack回车。如果看到如下的字样,说明jstack是可用的。
Usage:
    jstack [-l][-e] <pid>
        (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实现的锁。
点击查看更多内容
					为 TA 点赞
										
				 评论
				共同学习,写下你的评论
评论加载中...
作者其他优质文章
					正在加载中
				
			感谢您的支持,我会继续努力的~
		扫码打赏,你说多少就多少
		赞赏金额会直接到老师账户
		支付方式
		打开微信扫一扫,即可进行扫码打赏哦
	 
                 
             
			 
					