死锁
- 定义:
死锁是指两个或者两个以上的线程在线程执行过程中,由于竞争资源而造成的阻塞问题,若无外力作用下,他们将无法推进下去。此时处于死锁状态。
- 死锁产生的原因:
1、因竞争资源产生死锁;
2、进程顺序推进不当发生死锁;
- 出现死锁的必要条件:
1、互斥条件:资源每次只能一个线程使用; ------》资源
2、请求与保持条件:一个线程因请求资源而阻塞时,对已经获取的资源保持不放; ----》线程
3、不可剥夺条件:线程已获取的资源,在未使用之前,不能强行剥夺;
4、循环等待条件:若干的线程之间形成一种头尾相连接的循环等待资源关系。
- 死锁的预防或解除:
解决死锁的途径:预防、避免、检测、恢复
1、预防死锁(破坏4个必要条件):(事前)
资源一次性分配(破坏请求与保持条件);
可剥夺资源:在线程未满足条件时,释放已占有的资源;
资源有序分配:系统给每类资源赋予一个编号,每个线程按编号递增请求资源,释放资源则相反;
2、 避免死锁:(事中)
允许线程动态地申请资源。系统在资源分配之前先计算资源分配的安全性,通过计算,若此次分配不会导致系统进入不安全状态,则给线程分配该资源,否则等待。
银行家算法
3、检测与接触死锁:(事后)
当线程发现进入死锁了,立即从死锁状态解除掉,采用方式
剥夺资源:从其他线程剥夺足够多的资源给死锁线程,以免解除死锁状态的线程。
- 引起死锁的案例:
1、生产者、消费者使用不当会产生死锁(wait()、notify()、notifyAll());
2、多线程获取多把锁;
lock1 lock2
lock1.lock;
lock2.lock;
lock2.unlock;
lock1.unlock;
3、哲学家就餐问题:https://blog.csdn.net/nn1__2970/article/details/90026383,转到此文章查看。
- 实际定位死锁问题的思路:
jdk提供的JAVA命令在哪里?
1.首先需要确定java进程是否发生死锁
2.打开jvisualvm工具,专门分析JVMCPU,内存使用情况,以及线程的运行信息查看当前java进程各个线程运行的状态(颜色)
3.通过jvisualvm的线程dump或者jstack命令,把当前java进程所有线程的调用堆栈信息打印出来
4.分析main线程和子线程有没有关键短语: waiting for(资源地址) waiting to lock(资源地址)
5.看线程函数调用栈,定位到源码上,具体问题具体分析 。
银行家算法
银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
- 背景:
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。 - 操作系统安全状态和不安全状态(安全序列和不安全序列):
安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。
- 如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。
- 不安全状态:不存在一个安全序列。不安全状态不一定导致死锁。
-
问题描述:
我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。 -
数据结构:
- 可利用资源向量Available:
是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目。如果Available[j]=K,则表示系统中现有Rj类资源K个。 - 最大需求矩阵Max:
这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i,j]=K,则表示进程i需要Rj类资源的最大数目为K。 - 分配矩阵Allocation:
这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i,j]=K,则表示进程i当前已分得Rj类资源的 数目为K。 - 需求矩阵Need:
这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成其任务。
Need[i,j]=Max[i,j]-Allocation[i,j]
银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。