Java死锁示例

面试过程中遇到,手写一个Java死锁的示例

如果线程A持有锁L并且想获得锁M,线程B持有锁M并且想获得锁L,那么这两个线程将永远等待下去,这种情况就是最简单的死锁形式。

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
public class DeadLock
{
private final Object left = new Object();
private final Object right = new Object();

public void leftRight() throws Exception
{
synchronized (left)
{
Thread.sleep(2000);
synchronized (right)
{
System.out.println("leftRight end!");
}
}
}

public void rightLeft() throws Exception
{
synchronized (right)
{
Thread.sleep(2000);
synchronized (left)
{
System.out.println("rightLeft end!");
}
}
}
}

注意这里一定要有”Thread.sleep(2000)”让线程睡一觉,不然一个线程运行了,另一个线程还没有运行,先运行的线程很有可能就已经连续获得两个锁了。写两个线程分别调用它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Thread0 extends Thread
{
private DeadLock dl;

public Thread0(DeadLock dl)
{
this.dl = dl;
}

public void run()
{
try
{
dl.leftRight();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Thread1 extends Thread
{
private DeadLock dl;

public Thread1(DeadLock dl)
{
this.dl = dl;
}

public void run()
{
try
{
dl.rightLeft();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

写个main函数调用一下:

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args)
{
DeadLock dl = new DeadLock();
Thread0 t0 = new Thread0(dl);
Thread1 t1 = new Thread1(dl);
t0.start();
t1.start();

while(true);
}

避免死锁的方式

既然可能产生死锁,那么接下来,讲一下如何避免死锁。

1、让程序每次至多只能获得一个锁。当然,在多线程环境下,这种情况通常并不现实

2、设计时考虑清楚锁的顺序,尽量减少嵌在的加锁交互数量

3、既然死锁的产生是两个线程无限等待对方持有的锁,那么只要等待时间有个上限不就好了。当然synchronized不具备这个功能,但是我们可以使用Lock类中的tryLock方法去尝试获取锁,这个方法可以指定一个超时时限,在等待超过该时限之后变回返回一个失败信息

:转载文章请注明出处,谢谢~