死锁是多进程环境下的一种假死现象,即产生死锁的进程都处于等待状态。只要满足了下面四个必要条件,就有可能产生死锁:
- 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
- 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
- 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
- 环路等待条件:是指进程发生死锁后,必然存在一个进程–资源之间的环形链
一旦产生了死锁,程序将不再往下执行。那么应该怎么分析程序是否产生了死锁呢?本节来介绍一种使用Java Dump分析死锁的方法。
1.包含死锁的程序
下面是一段包含死锁的程序:DeadLock.java
public class DeadLock {
final Object lockA = new Object();
final Object lockB = new Object();
public static void main(String[] args) {
DeadLock demo = new DeadLock();
demo.startLock();
}
public void startLock(){
ThreadA a= new ThreadA(lockA,lockB);
ThreadB b= new ThreadB(lockA,lockB);
//start threads
a.start();
b.start();
}
}
class ThreadA extends Thread{
private Object lockA = null;
private Object lockB = null;
public ThreadA(Object a, Object b){
this.lockA = a;
this.lockB = b;
}
public void run() {
synchronized (lockA) {
System.out.println("*** Thread A: ***: Lock A" );
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB) {
System.out.println("*** Thread A: ***: Lock B" );
}
}
System.out.println("*** Thread A: ***: Finished" );
}
}
class ThreadB extends Thread{
private Object lockA = null;
private Object lockB = null;
public ThreadB(Object a, Object b){
this.lockA = a;
this.lockB = b;
}
public void run() {
synchronized (lockB) {
System.out.println("*** Thread B: ***: Lock B" );
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockA) {
System.out.println("*** Thread B: ***: Lock A" );
}
}
System.out.println("*** Thread B: ***: Finished" );
}
}
说明:以上代码中,有两个共享资源lockA和lockB,同时启动两个线程a和b,其中线程a先申请资源lockA,然后睡3秒,再去申请资源lockB;线程b先申请资源lockB,然后也睡3秒,再去申请资源lockA。当线程a启动并申请到资源lockA然后睡3秒时,这时线程b启动并申请到资源lockB也睡3秒;等线程a睡醒后去申请资源lockB,发现资源lockB被其他线程占用,所以线程a就开始等待;等线程b睡醒后去申请资源lockA,发现资源lockA也被其他线程占用,然后线程b也开始等待。如此这般,a和b就进入了循环等待的死锁状态。
2.使用JDK的Thread Dump工具分析死锁
这里介绍一种在Windows和Linux下,使用JDK提供的Thread Dump工具分析死锁的办法。
1.Windows下使用Thread Dump分析死锁
(1)编译并执行DeadLock.java程序
image(2)按Ctrl + Break(或者fn + b)分析死锁
image image2.Linux下使用Thread Dump分析死锁
(1)编译并执行DeadLock.java程序
image(2)使用kill -3 PID分析死锁
新打开一个终端,查看jps进程号,使用kill -3 PID杀死死锁进程:
image原来的终端窗口会显示检测到的死锁信息:
image死锁分析是一门非常重要的技术手段。使用Thread Dump工具可以方便的检测出程序是否包含死锁。
本节介绍了Java中使用Thread Dump工具分析死锁的详细过程。祝你玩的愉快!
网友评论