面试官也怕的技能,一个Java岗位的offer就能产生死锁

用幽默浅显的言语来说死锁

半生:我已经拿到了机考的第一名,就差笔试第一名了

小一:我已经拿到了笔试的第一名,就差机考第一名了

面试官:我很看好你俩,继续"干", 同时拿到2个的第一名才能拿到offer,进入我XX大厂

半生:小一,你的笔试第一名,让我可好?

小一:做梦,我还要你的机考第一名呢!

半生:就你那水平,zz

小一:WTF,来干一架

半生:来呀,who怕who

于是:死锁产生了,狭路相逢勇者胜,电脑死机了。

 

什么是死锁?死锁的产生条件是什么?

1.死锁是指两个或多个线程互相等待对方释放所持有的资源,从而导致进程无法继续执行的一种情况。具体来说,死锁发生时线程会进入一个永久等待的状态,无法继续执行并最终导致程序无响应或崩溃。

2.产生死锁的条件,通常被称为死锁的四个必要条件,包括:

  1. 互斥条件(Mutual Exclusion):至少有一个资源被多个线程独占,也就是说一个资源同时只能被一个线程占用。
  2. 请求与保持条件(Hold and Wait):线程已经持有了至少一个资源,并且在等待获取其他线程占有的资源。
  3. 不可剥夺条件(No Preemption):已经获得的资源不能被其他线程抢占,只能由占有它的线程显示地释放。
  4. 循环等待条件(Circular Wait):多个线程形成一个循环等待的等待链,即每个线程都在等待下一个线程所持有的资源。

只有当上述四个条件同时满足时,死锁才可能发生。

下面上一段代码(有问题的代码,考考你们的眼力跟基本功)

 public static void main(String[] args) {
        final Object resource1 = new Object();
        final Object resource2 = new Object();

        Thread thread1 = new Thread(() -> {
            synchronized (resource1) {
                System.out.println("Thread 1:锁住offer1");
            }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resource2) {
                    System.out.println("Thread 1:锁住offer2");
                }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (resource2) {
                System.out.println("Thread 2:锁住offer2");
            }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resource1) {
                    System.out.println("Thread 2:锁住offer1");
                }
        });

        thread1.start();
        thread2.start();
    }

为什么这2个线程都锁不住这个offer?

面试官也怕的技能,一个Java岗位的offer就能产生死锁_第1张图片

肥水不流外人田,既然你们都锁不住这个offer,就让我来~

 

public static void main(String[] args) {
        final Object resource1 = new Object();
        final Object resource2 = new Object();

        Thread thread1 = new Thread(() -> {
            synchronized (resource1) {
                System.out.println("半生:锁住了机考第一名");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resource2) {
                    System.out.println("半生:笔试第一名");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (resource2) {
                System.out.println("小一:锁住了笔试第一名");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resource1) {
                    System.out.println("小一:锁住机考第一名");
                }
            }
        });

        thread1.start();
        thread2.start();
    }

面试官也怕的技能,一个Java岗位的offer就能产生死锁_第2张图片

又是你俩,干啥呢,死锁了呀~offer不止一个呀,就不能友好相处,快乐的玩耍同时都拿到offer么

于是:解决死锁的方式来了~

退一步想阔天空,你好我好大家好

public static void main(String[] args) {
        final Object resource1 = new Object();
        final Object resource2 = new Object();

        Thread thread1 = new Thread(() -> {
            synchronized (resource1) {
                System.out.println("半生:获得了机考第一名");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resource2) {
                    System.out.println("半生:获得了笔试第一名");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (resource1) {
                System.out.println("小一:获得了笔试第一名");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resource2) {
                    System.out.println("小一:获得了机考第一名");
                }
            }
        });

        thread1.start();
        thread2.start();
    }

面试官也怕的技能,一个Java岗位的offer就能产生死锁_第3张图片

只要稍微改下获取资源的顺序,半生跟小一就分别都获取了机考,笔试第一名,都收到了XX大厂offer

打破死锁的方式有多种,只要四个死锁的必要条件去其一就可以了

常用的有以下几种常见的方式可以用来解决死锁问题

  1. 避免循环等待:通过对资源加锁的顺序进行规定,以避免线程之间互相等待对方所持有的资源。可以通过排序或编号等方式来约定资源的获取顺序,从而避免循环等待。

  2. 破坏请求与保持条件:允许线程在请求资源时一次性获取所有需要的资源,或者在获取某个资源时释放已经占有的资源。这样可以避免一个线程持有一个资源而等待另一个资源被释放的情况。

  3. 使用资源剥夺:当一个线程请求资源时,如果资源已经被其他线程占有,则可以暂时剥夺其他线程对该资源的锁定,以满足当前线程的需求。被剥夺的线程可以等待一段时间后再重新申请资源。

  4. 使用超时机制:在获取锁资源时设置一个超时时间,在规定时间内无法获取到资源则放弃获取,释放已占有的资源,然后重新尝试。

  5. 死锁检测和恢复:通过检测系统中的死锁情况,对存在死锁的线程进行恢复或终止。常见的死锁检测算法包括资源分配图算法和银行家算法。

需要注意的是,不同的解决方式适用于不同的场景和问题,选择合适的方式需要根据具体情况进行评估。另外,预防死锁问题是更好的做法。在设计和实现时,尽量避免存在可能导致死锁的条件,从根本上杜绝死锁问题的发生。

 

你可能感兴趣的:(java知识,面试题,java,后端,面试,开发语言)