Java经典面试题之写个死锁

	最近有朋友去面试Java,被问到多线程呀、锁呀相关的知识,朋友balabala也基本能答上来,
然后面试官突然要求手写个简单的死锁出来,朋友一下子就懵住了~~,平时光看理论了,谁知道还
要手撕代码...,关键还乍写不出来...

	△:大环境这么差,面试还是要好好准备。

文章目录

          • 一、先上代码,非常简单
          • 二、检查死锁
          • 三、产生死锁的4个必要条件

一、先上代码,非常简单
public class DeadlockTest {
	//定义2个资源
    private static final Integer a = 0;
    private static final Integer b = 1;

    public static void main(String[] args) {
        //启动2个线程,分别调用getA()和getB()
        new Thread(DeadlockTest::getA).start();
        new Thread(DeadlockTest::getB).start();
    }
	static void getA() {
		//用synchronized 对a对象加锁
        synchronized (a) {
            System.out.println(Thread.currentThread().getName() + "获取到A锁");
            try {
                //等待500ms,再去获取B资源锁,让另一个线程有时间去独占b
                Thread.sleep(500);
                getB();
                System.out.println(Thread.currentThread().getName() + "获取到B锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static void getB() {
        synchronized (b) {
            System.out.println(Thread.currentThread().getName() + "获取到B锁");
             try {
                //等待500ms,再去获取A资源锁,让另一个线程有时间去独占a
                Thread.sleep(500);
            	getA();
            	System.out.println(Thread.currentThread().getName() + "获取到A锁");
             } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果:

Thread-0获取到A锁
Thread-1获取到B锁	

OK,死锁产生了。

原因: Thread-0在拿到a对象的监视器锁(后文简称“A锁”)之后,又要去拿b对象的监视器锁(简称“B锁”),而此时B锁在Thread-1手中,于是Thread-0只能阻塞,等待B锁被Thread-1释放。
对Thread-1而言,亦是如此,死锁产生。


二、检查死锁

很多可视化工具可以,比如jdk自带jConsole,这边只说2个简单的方式。

  1. JDK命令行工具jps、jstack。

    1)jps获取当前运行的java进程,拿到pid。如下图:
    Java经典面试题之写个死锁_第1张图片
    2)jstack pid 查看堆栈信息
    Java经典面试题之写个死锁_第2张图片

  2. IDEA在控制台点击Dump Threads图标
    Java经典面试题之写个死锁_第3张图片


三、产生死锁的4个必要条件

1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

在上面代码中就是通过synchronized加锁,该锁是独占的、排它的。一个线程获取到之后,
不允许第二个线程同时获取。

2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

 Thread-0拿到A锁的同时,又要请求B锁,但B锁被 Thread-1占有,所以要阻塞自己,等待B资源。

3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

Thread-0不能抢占Thread-1已拥有的资源,只能等待其主动释放。

4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

Thread-0等待Thread-1占用的资源B,Thread-1等待Thread-0占用的资源A,形成环路等待条件。

你可能感兴趣的:(java,并发,java多线程)