其他分享
首页 > 其他分享> > 春招冲刺Day2 [操作系统] --来聊聊死锁呗?

春招冲刺Day2 [操作系统] --来聊聊死锁呗?

作者:互联网

死锁

1.死锁的产生

死锁是在一组进程中的每一个进程都占有了资源,并且都在等待其他进程所占有的资源,这样会导致进程无限期等待下去,无法推进
产生死锁的4个条件
在这里插入图片描述

2.处理死锁

目前处理死锁的方法主要有以下4种

2.1预防死锁

所谓预防死锁,就是要破坏产生死锁的4个条件中的一个或几个,预防死锁是一种较容易实现的方式,已被广泛使用

我们给资源加锁的目的,就是为了限制进程互斥访问共享资源,因此不考虑破坏互斥条件!!

该条件是进程获取了一部分资源,并且请求其他资源,如果要破坏该条件,那么可以让进程获取到需要的全部资源,如果获取不到,就进入等待,然后释放掉占用的部分资源

这样的确可以预防死锁,但是一个进程在不同的时间段所需要的资源是不同的,如果一上来就占用到全部资源,这样会导致系统的利用率极低,容易造成饥饿,其他进程久久获取不到资源

针对JAVA开发中,我们可以尝试在加锁时,设置超时时间,如果在规定时间内没有获取到锁,则释放已经获取到的资源

具体对用可以使用ReentrantLock中的tryLock方法
注意不能使用Synchronized,因为Synchornized获取不到锁,会阻塞等待,不会释放已经占有的资源!!!

该条件是值进程所占有的资源只能由自己来释放,不能让其他进程所抢占,如果要破坏该条件,那么一个办法就是把占有资源的进程kill掉,这显然不可取!!

比如下面线程A和线程B,申请获取资源的顺序不同,那么就有可能造成死锁!
如果我们让A,B都按照相同的顺序申请资源,比如都先申请a,再申请b,这样就不会造成死锁
在这里插入图片描述
针对JAVA来说k,我们可以给锁对象按照hashCode的大小排序,然后按照这个顺序来获取锁,但是这种方法只适用于线程数,资源数较少的情况,如果过多,那么应该使用银行家算法(下文!!)

2.2 避免死锁

`在死锁避免中,把系统的状态分为安全状态和不安全状态,当进程申请资源时,检测系统的状态,如果系统处于安全状态时,那么可以把资源分配给进程,反之,当系统处于不安全状态时,此时不应该分配资源给进程,让进程等待,因为不安全状态下分配资源给进程可能会引起死锁!!
注意是可能引起死锁!!!不是一定会引起死锁!!
在这里插入图片描述

最具有代表性的死锁避免算法是银行家算法,是一种动态的检测资源分配状态的算法!
某个进程请求资源,先假定分配给该进程,如果分配后系统的状态是安全的(找到一个安全序列),那么就可以分配,否则不嫩分配!!
链接: 银行家算法.

银行家算法中的数据结构
  为了实现银行家算法,在系统中必须设置这样四个数据结构,分别用来描述系统中可利用的资源、所有进程对资源的最大需求、系统中的资源分配,以及所有进程还需要多少资源的情况。
  (1) 可利用资源向量 Available。这是一个含有 m 个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果 Available[j] = K,则表示系统中现Rj类资源K个。
  (2) 最大需求矩阵Max。这是一个n x m的矩阵,它定义了系统中n个进程中的每个进程对m类资源的最大需求。如果Max[i,j] = K,则表示进程i需要Rj 类资源的最大数目为K。
  (3) 分配矩阵 Allocation。这也是一个n x m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果 Allocation[i,jl = K,则表示进程i当前己分得Rj类资源的数目为K。
  (4) 需求矩阵Need.这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j] = K,则表示进程i还需要Rj类资源K个方能完成其任务。
上述三个矩阵间存在下述关系:
              Need[i,j] = Max[i,j] - allocation[i, j]

举例说明:
在这里插入图片描述
假设此时P1进程需要请求资源(1,0,1),那我们先假设分配给P1
在这里插入图片描述
此时再判断系统的安全状态,发现此时Available中为(0,1,1),不能使系统处于安全状态,因此不能响应P1进程的请求!!!


如果在系统中既不采取预防措施,也没有死锁避免算法,系统很可能发生死锁,此时应该提供死锁检测算法和死锁解除算法

3.死锁检测和死锁解除

死锁检测可以使用资源分配图,其中包括资源节点和进程节点,然后转化为等待图,如果等待图中有环,则产生死锁,否则没有死锁!!
在这里插入图片描述

当发现有进程死锁后,便应立即把它从死锁状态中解脱出来,常采用的方法有:

剥夺资源:从其他进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态.消除为止;所谓代价是指优先级、运行代价、进程的重要性和价值等。

3.1JAVA如何检查死锁

面试官:用代码模拟死锁??!!(这里用Synchronized模拟,也可以用ReentrantLock!!)

public static void main(String[] args) {
    final Object a = new Object();
    final Object b = new Object();
    Thread threadA = new Thread(new Runnable() {
        public void run() {
            synchronized (a) {
                try {
                    System.out.println("now i in threadA-locka");
                    Thread.sleep(1000l);
                    synchronized (b) {
                        System.out.println("now i in threadA-lockb");
                    }
                } catch (Exception e) {
                    // ignore
                }
            }
        }
    });
 
    Thread threadB = new Thread(new Runnable() {
        public void run() {
            synchronized (b) {
                try {
                    System.out.println("now i in threadB-lockb");
                    Thread.sleep(1000l);
                    synchronized (a) {
                        System.out.println("now i in threadB-locka");
                    }
                } catch (Exception e) {
                    // ignore
                }
            }
        }
    });
 
    threadA.start();
    threadB.start();
}

在这里插入图片描述

Jstack

jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息
具体操作是:
首先利用JPS找到当前进程的ID,然后利用Jstack -F 进程ID,查看当前进程对应的堆栈信息
在这里插入图片描述
在这里插入图片描述

Jconsole

Jconsole是JDK自带的监控工具,在JDK/bin目录下可以找到。它用于连接正在运行的本地或者远程的JVM,对运行在Java应用程序的资源消耗和性能进行监控,并画出大量的图表,提供强大的可视化界面。而且本身占用的服务器内存很小,甚至可以说几乎不消耗。

我们在命令行中敲入jconsole命令,会自动弹出以下对话框,选择产生死锁的对应进程即可查看!!
在这里插入图片描述
在这里插入图片描述

标签:状态,--,系统,算法,死锁,春招,进程,资源
来源: https://blog.csdn.net/weixin_46273997/article/details/121991955