ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

面试题:实现一个死锁(Java版),产生死锁的四大必要条件,如何避免死锁,如何解决死锁

2022-02-26 10:30:19  阅读:150  来源: 互联网

标签:面试题 加锁 Java Thread Lock 死锁 线程 进程


实现一个最简单的死锁(Java版)

```java
/**
 * @author wall
 * @date 2019/7/29  16:42
 * @description 实现一个死锁:A线程获取B线程占有的锁,B线程获取A线程占有的锁
 */
public class DeadLock {
    //定义两把锁
    private static ReentrantLock lockA = new ReentrantLock();
    private static ReentrantLock lockB = new ReentrantLock();
    //测试
    public static void main(String[] args) {
        //启动线程A,B
        new Thread(new A()).start();
        new Thread(new B()).start();
    }
 
    static class A implements Runnable{
        @Override
        public void run() {
            Thread.currentThread().setName("A线程");
            //获取锁A
            lockA.lock();
            System.out.println(Thread.currentThread().getName()+"获取锁A");
            //模拟业务操作
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //再获取锁B
            lockB.lock();
            System.out.println(Thread.currentThread().getName()+"获取锁B");
            lockA.unlock();
            lockB.unlock();
        }
    }
 
    static class B implements Runnable{
        @Override
        public void run() {
            Thread.currentThread().setName("B线程");
            //获取锁B
            lockB.lock();
            System.out.println(Thread.currentThread().getName()+"获取锁B");
            //模拟业务操作
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //再获取锁A
            lockA.lock();
            System.out.println(Thread.currentThread().getName()+"获取锁A");
        }
    }
}

产生死锁的四大必要条件
①资源互斥/资源不共享

互斥条件:一个资源每次只能被一个进程使用。

②占有和等待/请求并保持

(请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

③资源不可剥夺

进程已获得的资源,在末使用完之前,不能强行剥夺。

④环路等待

若干进程之间形成一种头尾相接的循环等待资源关系。

举个例子▼

小明有键盘,小白有鼠标,小明要用电脑打游戏,小白要用电脑做PPT,小明没有鼠标没法打游戏,小白没有键盘没法做PPT,小明等小白把鼠标给自己,小白也等小明把键盘给自己,但是小明不愿意把键盘给小白,小白也不愿意把鼠标给小明,小明和小白也不能互相抢键盘和鼠标,他俩之间就形成了死锁。

避免死锁的方式

1、银行家算法
2、避免多次锁定。尽量避免同一个线程对多个 Lock 进行锁定。例如上面的死锁程序,主线程要对 A、B 两个对象的 Lock 进行锁定,副线程也要对 A、B 两个对象的 Lock 进行锁定,这就埋下了导致死锁的隐患。
具有相同的加锁顺序。(给锁添加顺序)如果多个线程需要对多个 Lock 进行锁定,则应该保证它们以相同的顺序请求加锁。比如上面的死锁程序,主线程先对 A 对象的 Lock 加锁,再对 B 对象的 Lock 加锁;而副线程则先对 B 对象的 Lock 加锁,再对 A 对象的 Lock 加锁。这种加锁顺序很容易形成嵌套锁定,进而导致死锁。如果让主线程、副线程按照相同的顺序加锁,就可以避免这个问题。
3、使用定时锁。程序在调用 acquire() 方法加锁时可指定 timeout 参数,该参数指定超过 timeout 秒后会自动释放对 Lock 的锁定,这样就可以解开死锁了。
4、死锁检测。死锁检测是一种依靠算法机制来实现的死锁预防机制,它主要是针对那些不可能实现按序加锁,也不能使用定时锁的场景的。

死锁的解除
1、资源剥夺法

挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。

2、撤销进程法

强制撤销部分、甚至全部死锁进程并剥夺这些进程的资源。撤销的原则可以按进程优先级和撤销进程代价的高低进行。

3、进程回退法

让一(多)个进程回退到足以回避死锁的地步,进程回退时自愿释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点。
————————————————
版权声明:本文为CSDN博主「虚拟土壤」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42228338/article/details/97686461

标签:面试题,加锁,Java,Thread,Lock,死锁,线程,进程
来源: https://blog.csdn.net/weixin_44321785/article/details/123146040

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有