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 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦