上一篇介绍死锁的博客提到了
- 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
那么今天,我准备自己写一个程序来模拟死锁的产生。
简单起见,我这里只设置两个资源a, b。假如有一个线程持有a而想去获取b,而另一个线程持有b而恰巧又想获取a,那理论上正好可以满足死锁产生的四个条件。
public class MutiThread implements Runnable {
private Object a;
private Object b;
private int flag;
public MutiThread(Object a, Object b, int flag) {
this.a = a;
this.b = b;
this.flag = flag;
}
public void task1() throws InterruptedException {
synchronized (a) {
synchronized (b) {
System.out.println(Thread.currentThread().getName());
}
}
}
public void task2() throws InterruptedException {
synchronized (b) {
Thread.yield();//线程让步
synchronized (a) {
System.out.println(Thread.currentThread().getName());
}
}
}
@Override
public void run() {
while (true) {
try {
if (flag == 1) {
task1();
} else {
task2();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这个多线程的类就可能发生死锁,测试如下:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class DeadLockTest {
public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
ExecutorService excu = Executors.newFixedThreadPool(5); //创建一个固定大小为5的线程池
for (int flag = 0; flag < 2; flag++) {
excu.execute(new MutiThread(a, b, flag));
}
}
}
运行结果:
pool-1-thread-1
pool-1-thread-1
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
pool-1-thread-2
控制台过一会儿就不动了,但是程序运行没有终止。在这个例子里,说明程序发生了死锁了。
实际开发中,如果程序产生了死锁,那么情况一定比我这个demo复杂很多,比如循坏链不会像这里的a ->b->a这么简单。因此我们可以用一些Java栈跟踪工具来定位死锁,再用比如上篇博客提到的死锁的预防和排除办法来解决死锁。