Java并发编程(十六)死锁状态

死锁

在实际应用上,使用锁的环境远远要多于使用无锁。但是经常使用锁,一般都会面对一个问题,那就是死锁,现在用一个例子,简单的阐述死锁。

哲学家的餐桌

哲学家就餐问题就是一个常见的死锁问题。有四个哲学家坐在一个正方形的桌子上面,每个桌角都放置有一个叉子,而哲学家必须使用两个叉子才能正常进餐,但是哲学家们并不一直用餐,它们有时候还会停止进餐,用一段时间去思考哲学问题,这样的话,餐桌上的叉子就一直都处于被竞争的状态,最多时,可以同时存在两个哲学家进餐,两个哲学家思考。但是,又因为哲学家们从不进行交谈,这就会产生一个问题,如果有一个哲学家只拿到了右边的叉子,需要等待左边的叉子的时候,左边的哲学家也在等待他左边的叉子,这样互相等待而不行动的状态,称之为死锁状态。这里就举一个最简单的例子,只有两个哲学家在吃饭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class test extends Thread{
protected Object tool;
static Object f1=new Object();
static Object f2=new Object();

public test(Object tool) {
this.tool = tool;
if (tool==f1){
this.setName("哲学家A");
}
if (tool==f2){
this.setName("哲学家B");
}
}

public static void main(String[] args) throws InterruptedException {
test 哲学家A=new test(f1);
test 哲学家B=new test(f2);
哲学家A.start();
哲学家B.start();
Thread.sleep(1000);
}

@Override
public void run() {
if (tool==f1){
synchronized (f1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (f2){
System.out.println("哲学家A开始进餐");
}
}
}
if (tool==f2){
synchronized (f2){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (f1){
System.out.println("哲学家B开始进餐");
}
}
}
}
}

启动后发现进程并不会结束,将永久运行一下,因为它们在互相获取彼此的叉子的时候,又互相被锁住了。此时打开任务管理器,可以看到并不占用CPU ,因为产生了死锁,谁都没有行动。

也可以使用jps工具和jstack工具(只要能使用javac,就能使用这些工具)从cmd打印出到底出了什么问题哦!

jps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Found one Java-level deadlock:
=============================
"哲学家B":
waiting to lock monitor 0x000000000ae4f488 (object 0x00000000db0a48a0, a java.lang.Object),
which is held by "哲学家A"
"哲学家A":
waiting to lock monitor 0x000000000ae4c9e8 (object 0x00000000db0a48b0, a java.lang.Object),
which is held by "哲学家B"

Java stack information for the threads listed above:
===================================================
"哲学家B":
at test.run(test.java:46)
- waiting to lock <0x00000000db0a48a0> (a java.lang.Object)
- locked <0x00000000db0a48b0> (a java.lang.Object)
"哲学家A":
at test.run(test.java:34)
- waiting to lock <0x00000000db0a48b0> (a java.lang.Object)
- locked <0x00000000db0a48a0> (a java.lang.Object)

Found 1 deadlock.