死锁

1. 死锁

指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进

1.1 死锁产生条件

  • 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
  • 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
  • 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
  • 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

1.2 死锁示例代码

1.3 死锁检测

  • jps
  • jstack

1.4 解决死锁的基本方法

  • 破坏占用且等待条件

    • 一次性申请所有的资源
    • 只要有一个资源得不到分配,也不给这个进程分配其他的资源
  • 破坏不可剥夺条件

    当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源
    破坏不抢占要能够主动释放它占有的资源,但synchronized是做不到的。原因为synchronized申请不到资源时,线程直接进入了阻塞状态,而线程进入了阻塞状态也就没有办法释放它占有的资源了。不过SDK中的java.util.concurrent提供了Lock解决这个问题。
    显式使用Lock类中的定时tryLock功能来代替内置锁机制,可以检测死锁和从死锁中恢复过来。使用内置锁的线程获取不到锁会被阻塞,而显式锁可以指定一个超时时限(Timeout),在等待超过该时间后tryLock就会返回一个失败信息,也会释放其拥有的资源。

  • 破坏循环等待条件

    系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反

1.5 银行家算法

银行家算法(Banker’s Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。
在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。
银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构。

  • 1.5.1 数据结构

    • 可利用资源向量 Available

      这是一个含有 m 个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果 Available[j] = K,则表示系统中现Rj类资源K个。

    • 最大需求矩阵Max

      这是一个n x m的矩阵,它定义了系统中n个进程中的每个进程对m类资源的最大需求。如果Max[i,j] = K,则表示进程i需要Rj 类资源的最大数目为K

    • 分配矩阵 Allocation

      这也是一个n x m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果 Allocation[i,jl = K,则表示进程i当前己分得Rj类资源的数目为K

    • 需求矩阵Need

      这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j] = K,则表示进程i还需要Rj类资源K个方能完成其任务

参考文章

posted @ 2020-09-27 20:36  donfaquir  阅读(149)  评论(0编辑  收藏  举报