Java线程死锁原因:不同线程都在等待根本不可能被释放的锁,从而导致所有的任务都无法继续完成。举个栗子:两个线程互相等待对方释放锁。
/**
* Created by LZF on 2017/7/14.
* 学习:如何查看多线程死锁
*/
class DealThread implements Runnable{
public String username;
public Object lock1 = new Object();
public Object lock2 = new Object();
public void setFlag(String username){
this.username = username;
}
@Override
public void run(){
if(username.equals("a")){
synchronized (lock1){
try{
System.out.println("username = " + username);
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
synchronized (lock2){
System.out.println("按lock1->lock2代码顺序执行了");
}
}
}
if(username.equals("b")){
synchronized (lock2){
try{
System.out.println("username = " + username);
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
synchronized (lock1){
System.out.println("按lock2->lock1代码顺序执行了");
}
}
}
}
}
public class Run_13 {
public static void main(String[] args){
try{
DealThread t1 = new DealThread();
t1.setFlag("a");
Thread thread1 = new Thread(t1);
thread1.start();
Thread.sleep(100);
t1.setFlag("b");
Thread thread2 = new Thread(t1);
thread2.start();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
结果:出现死锁,无法继续执行
在使用JDK自带的工具监测是否有死锁的现象前,先介绍两个命令:
- jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有Java进程pid的命令,简单实用,非常适合在Linux/unix平台上简单察看当前java进程的一些简单情况。
- jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。
命令格式:jstack [ option ] pid
[options]选项 :
-F :当’jstack [-l] pid’没有响应的时候强制打印栈信息;
-l :长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.
-m: 打印java和native c/c++框架的所有栈信息. -h | -help打印帮助信息
pid :需要被打印配置信息的java进程id,可以用jps工具查询
可以使用JDK自带的工具监测是否有死锁的现象。进入CMD -> 打开JDK的安装文件夹中的bin目录 -> 执行jsp命令 如下图所示:
得到运行的线程Run的id值是13088,再执行jstack命令,监测出有死锁现象,如下图所示:
只要互相等待对方释放锁就有可能出现死锁。
参考书籍:《Java多线程编程核心技术》–高洪岩