死锁(Dead Lock):两个或以上的运算单元(进程、线程或协程),都在等待对方停止执行,以取得系统资源,但是没有一方提前退出。
1、模拟异常代码,开启两个线程,互相等待对方释放资源。sleep(2000)保证,两个线程第一时间能成功持有各自的第一个对象锁。
private static Object lock1 = new Object();
private static Object lock2 = new Object();
/**
* 线程互相等待对方释放资源,产生死锁
* @return
* @throws InterruptedException
*/
@RequestMapping("/user/deadLock")
public String deadLock() throws InterruptedException {
new Thread(()->{
synchronized (lock1){
System.out.println("thread1 begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2){
System.out.println("thread1 end");
}
}
}).start();
new Thread(()->{
synchronized (lock2){
System.out.println("thread2 begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1){
System.out.println("thread2 end");
}
}
}).start();
return "sucess";
}
找到该java进程,pid=1737
ps -ef|grep java
当页面发起如下请求后
http://101.132.143.77:8089/user/deadLock
通过日志,发现两个线程都开始了,但没有结束
用jstack命令,可以直接分析该进程是否存在死锁
jstack 1737
底部分析出结果:found 1 deadlock,发现一个死锁
死锁的原因:
Thread-3等待获取对象<0x00000000c9f7c730>的锁,同时占有了对象<0x00000000c9f7c740>的锁。
Thread-4等待获取对象<0x00000000c9f7c740>的锁,同时占有了对象<0x00000000c9f7c730>的锁。
两个线程互相等待对方持有的资源
此时线程3、4的状态都是BLOCKED
线程的状态:
NEW:未启动的。不会出现先dump中。
RUNNABLE:运行中状态,在虚拟机内执行的。locked代表线程获得了锁。
BLOCKED:受阻塞并等待监视器锁。被某个锁给block住了。
WATING:无限期等待另一个线程执行特定操作。等待某个condition或monitor发生。
TIMED_WATING:有时限的等待另一个线程的特定操作。
TERMINATED:已退出的。
调用修饰:表示线程在方法调动时,额外的重要操作
locked<地址>目标:通过synchronized关键字,成功获取到了对象的锁,成为监视器的拥有者,在临界区内操作。
waiting to lock<地址>目标:通过synchronized关键字,没有获取到对象的锁,线程在监视器的进入区等待。在调用栈顶出现,线程状态为Blocked。
waiting on <地址>目标:通过synchronized关键字,成功获取到了对象的锁后,调用了wait方法,进入对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING。
parking to wat for<地址>目标:park是基本的线程阻塞原语,不通过监视器在对象上阻塞。
导出堆栈信息到文件:
jstack pid > dump.txt