在面试过程中面试官可能会问你关于锁的知识,并让你手写一个死锁的案例。下面我们来写一个简单的小Demo来实现一个死锁。

死锁案例

 1 public class DeadLockDemo extends Thread{
 2
 3     String lockA ;
 4     String lockB;
 5     public DeadLockDemo(String name,String lockA,String lockB){
 6         super(name);
 7         this.lockA = lockA;
 8         this.lockB = lockB;
 9     }
10
11     public void run() {
12         synchronized (lockA){
13             System.out.println(Thread.currentThread().getName() + "拿到了" + lockA + ",等待拿到" + lockB);
14             try {
15                 Thread.sleep(1000);
16                 synchronized (lockB){
17                     System.out.println(Thread.currentThread().getName() + "拿到了" + lockB);
18                 }
19             } catch (InterruptedException e) {
20                 e.printStackTrace();
21             }
22
23         }
24     }
25
26     public static void main(String[] args){
27         String lockA = "lockA";
28         String lockB = "lockB";
29         DeadLockDemo threadA = new DeadLockDemo("ThreadA", lockA, lockB);
30         DeadLockDemo threadB = new DeadLockDemo("ThreadB", lockB, lockA);
31         threadA.start();
32         threadB.start();
33         try {
34             threadA.join();
35             threadB.join();
36         } catch (InterruptedException e) {
37             e.printStackTrace();
38         }
39     }
40 }

这段代码 显而易见会block住 来看结果

ThreadA拿到了lockA,等待拿到lockB
ThreadB拿到了lockB,等待拿到lockA

并且程序是一直运行着的状态,那么程序出了这种状况应该怎么去排查呢?对于简单的案例我们直接用jstack就可以来查看具体是哪里的问题了

排查死锁

首先使用jps查看当前程序的进程的ID

然后使用jstack来打印信息

从上面可以看到两个线程被block住了 然后自己去查看出错的代码进行分析

怎么预防死锁

死锁的产生让人头疼,那么怎么去预防死锁呢?

预防死锁得先知道死锁产生的条件

1.互斥(一个资源一次只能被一个进程访问)

2. 请求与保持(一个进程因请求资源而阻塞时,对自己的资源不释放)

3.不可剥夺(进程已获得的资源,不能被抢占剥夺)

4. 循环等待(进程间形成等待的循环关系)

那么我们只要破坏其中的一项就不会产生死锁。

预防的方法主要有:

1. 著名的银行家算法

2. 可以使用带时间的tryLock(long timeout, TmeUnit unit)方法

3. 避免使用多个锁

......

01-25 11:57