Java中死锁的简单例子及其避免

死锁:当一个线程永远地持有一个锁,并且其他线程都尝试获得这个锁时,那么它们将永远被阻塞。比如,线程1已经持有了A锁并想要获得B锁的同时,线程2持有B锁并尝试获取A锁,那么这两个线程将永远地等待下去。

我们来看一个死锁的简单例子:

 1 public class DeadLockTest
 2 {
 3     private static Object A = new Object(), B = new Object();
 4 
 5     public static void main(String[] args)
 6     {
 7         new Thread(() -> {
 8             System.out.println("线程1开始执行...");
 9             synchronized (A)
10             {
11                 try
12                 {
13                     System.out.println("线程1拿到A锁");
14                     //休眠两秒让线程2有时间拿到B锁
15                     Thread.sleep(2000);
16                 } catch (Exception e)
17                 {
18                     e.printStackTrace();
19                 }
20                 synchronized (B)
21                 {
22                     System.out.println("线程1拿到B锁");
23                 }
24             }
25         }).start();
26         
27         new Thread(() -> {
28             System.out.println("线程2开始执行...");
29             synchronized (B)
30             {
31                 try
32                 {
33                     System.out.println("线程2拿到B锁");
34                     //休眠两秒让线程1有时间拿到A锁
35                     Thread.sleep(2000);
36                 } catch (Exception e)
37                 {
38                     e.printStackTrace();
39                 }
40                 synchronized (A)
41                 {
42                     System.out.println("线程2拿到A锁");
43                 }
44             }
45         }).start();
46         
47     }
48 }

 

运行结果:

 

从运行结果可看到,线程1拿到了A锁,并尝试去获取B锁,与此同时线程2拿到了B锁并尝试去获取A锁,此时线程1和线程2就陷入了无限的等待,形成死锁。

那么要怎么预防死锁呢?下面介绍几个常见方法:

1、避免一个线程同时获取多个锁

2、避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源

3、尝试使用定时锁,使用lock.tryLock来代替使用内置锁。

详情可参考《Java并发编程实战》

posted @ 2017-09-15 16:11  不速之客  阅读(7125)  评论(0编辑  收藏  举报