死锁问题
有这样一个场景:一个中国人和一个美国人在一起吃饭,美国人拿了中国人的筷子,中国人拿了美国人的刀叉,两个人开始争执不休:
中国人:“你先给我筷子,我再给你刀叉!”
美国人:“你先给我刀叉,我再给你筷子!”
…………
上面场景的结果可想而知,两个人都吃不到饭。这个例子中的中国人和美国人相当于不同的线程,筷子和刀叉就相当于锁。两个线程在运行时都在等待对方的锁,这样便造成了程序的停滞,这种现象称为死锁。接下来通过中国人和美国人吃饭的案例来模拟死锁问题,如文件1所示。
文件1 Example15.java
1 class DeadLockThread implements Runnable {
2 // 定义两个不同的锁对象
3 static Object chopsticks = new Object();
4 static Object knifeAndFork = new Object();
5 private boolean flag;
6 DeadLockThread(boolean flag) {
7 this.flag = flag;
8 }
9 public void run() {
10 if (flag) {
11 while (true) {
12 // chopsticks锁对象上的同步代码块
13 synchronized (chopsticks) {
14 System.out.println(Thread.currentThread().getName()
15 + "---if---chopsticks");
16 // knifeAndFork锁对象上的同步代码块
17 synchronized (knifeAndFork) {
18 System.out.println(Thread.currentThread().getName()
19 + "---if---knifeAndFork");
20 }
21 }
22 }
23 } else {
24 while (true) {
25 // knifeAndFork锁对象上的同步代码块
26 synchronized (knifeAndFork) {
27 System.out.println(Thread.currentThread().getName()
28 + "---else---knifeAndFork");
29 // chopsticks锁对象上的同步代码块
30 synchronized (chopsticks) {
31 System.out.println(Thread.currentThread().getName()
32 + "---else---chopsticks");
33 }
34 }
35 }
36 }
37 }
38 }
39 public class Example15 {
40 public static void main(String[] args) {
41 // 创建两个DeadLockThread对象
42 DeadLockThread thread1 = new DeadLockThread(true);
43 DeadLockThread thread2 = new DeadLockThread(false);
44 // 创建并开启两个线程
45 new Thread(thread1, "Chinese").start();
46 new Thread(thread2, "American").start();
47 }
48 }
运行结果如图1所示。
图1 运行结果
文件1中,创建了两个名为Chinese和American的线程,分别执行run()方法中if和else代码块中的同步代码块。Chinese线程中拥有chopsticks锁,只有获得knifeAndFork锁才能执行完毕,而American线程拥有knifeAndFork锁,只有获得chopsticks锁才能执行完毕,两个线程都需要对方所占用的锁,但是都无法释放自己所拥有的锁,于是这两个线程都处于了挂起状态,从而造成了如图1所示的死锁。