避免死锁-----银行家算法详解

2024-01-22 00:10

本文主要是介绍避免死锁-----银行家算法详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

​ 避免死锁同样属于事先预防的策略,但是并不是事先采取某种限制措施来破坏死锁的必要条件,而是在资源的动态分配过程中,防止系统进入不安全状态,以避免发生死锁。避免死锁这种方法对资源的分配限制条件较弱(相比于预防死锁),以期望获得更好的系统性能。

​ 关于安全状态和不安全状态的概念,可以参看这篇博文。

​ 银行家算法是我们的老朋友迪杰斯特拉为T.H.E系统设计的一种避免死锁产生的算法。该算法最初是为银行系统设计的,为了保证银行在发放现金贷款时,不会发生不能满足所有客户需要的情况。

​ 银行家算法要求,每个新进程在进入系统时,它必须申明在运行过程中,可能需要每种资源类型的最大单元数目,其数目不应超过系统所拥有的的资源总量。当进程请求一组资源时,系统必须首先确定是否有足够的资源分配给该进程。若有,在进一步的检测将这些资源分配给进程后,是否会是系统处于不安全状态;如果不会,才将资源分配给该进程,否则让进程等待

1.银行家算法中的数据结构

​ 为了实现银行家算法,在系统中必须设置这样四个数据结构,分别用来描述系统中可利用的资源、所有进程对资源的最大需求、系统中的资源分配、以及所有进程仍需要的资源情况。

  1. 可利用资源向量Available:这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果Available[j]=K,则表示系统中现有Rj类资源K个;
  2. 最大需求矩阵Max:这是一个n×m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i, j]=K,则表示进程Pi需要Rj类资源的最大数目为K;
  3. 分配矩阵Allocation:这也是一个n×m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i, j]=K,则表示进程Pi当前已分得Rj类资源的数目为K;
  4. 需求矩阵Need:这也是一个n×m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i, j]=K,则表示进程Pi还需要Rj类资源K个,方能完成其任务。

​ 上述的三个矩阵Max、Allocation、Need存在下述关系:

N e e d [ i , j ] = M a x [ i , j ] − A l l o c a t i o n [ i , j ] Need[i, j] = Max[i, j] - Allocation[i, j] Need[i,j]=Max[i,j]Allocation[i,j]

2.银行家算法

​ 设Requesti是进程Pi的请求向量,如果Requesti[j]=K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求Requesti(1,2,…,0)后(表示m类资源分别申请1,2,…,0个),系统按下述步骤进行检查:

  1. 如果Requesti[j]<=Need[i, j],(Requesti向量中的所有项都要判断)便转向步骤2;否则认为出错,因为他所需要的资源数(已经持有的+此次申请的)已经超过它之前声明的最大值。

  2. 如果Requesti[j]<=Available[i, j],(Requesti向量中的所有项都要判断)便转向步骤3;否则表示当前OS中尚无足够的资源满足进程Pi的此次申请,Pi进程阻塞,需要等待资源释放。

  3. 系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值(Requesti向量中的所有项都要操作):

    ​ Available[j] = Available[j] - Requesti[j]; //可用资源减去此次申请的资源

    ​ Allocation[i, j] = Allocation[i, j] + Requesti[j];//已经持有的资源加上此次申请的资源

    ​ Need[i, j] = Need[i, j] - Requesti[j];//仍需求资源减去此次申请的资源

  4. 系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则, 将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。

3.安全性算法

​ 安全性算法是银行家算法在第4步执行的子算法,用于检查试探着把资源分配给进程Pi后OS的安全状态。为了保证安全性检查不影响Available、Max、Allocation和Need,其新建两个向量(临时变量):

  • 工作向量Work:表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素(对应OS中的m类资源),在执行安全算法开始时,Work=Available(Work初始化为Available);
  • 结束标志向量Finsh:表示系统是否有足够的资源分配给所有进程,使之运行完成,它含有n个元素(对应OS中的进程数量n)。在执行安全算法开始时,Finsh中的所有位全为false,当有足够资源分配给进程Pi时,再令Finish[i] = true。

​ 安全性算法的执行步骤如下:

  1. 从进程集合中找到一个能满足下述两个条件的进程:①Finsh[i] == false;②Need[i, j]<=Work[j],其中0=<j<m,即进程Pi所需的所有资源可以申请获得;若找到,执行步骤2,否则执行步骤4。
  2. 当进程Pi获得所需的所有资源后,可顺利执行完毕,并释放出分配给它的资源,所以需执行以下步骤:①Work[j] = Work[j] + Allocation[i, j],其中0=<j<m,m为OS中的资源种类;②Finish[i] = true,表示进程Pi可以顺利执行完毕;③跳转到步骤1。
  3. 如果Finish向量中的所有位全部为true,即所有进程都可顺利执行完毕,则表示系统处于安全状态;否则,系统处于不安全状态。

​ 最后,将检测结果返回给步骤四,来决定此次资源请求是否分配。

​ 安全性算法其实际目的就是看是否能找到一个安全序列,如果存在一个所有进程都可顺利推进完成的安全序列,则表示此时OS是处于安全状态,在这个状态下不会产生死锁

4.一个例子

​ 下面我们通过一个例子来讲解银行家算法的执行过程。

​ 例题:假定系统中有五个进程{P0, P1, P2, P3, P4}和三类资源{A, B, C},各种资源的对应数量为10、5、7,在T0时刻的资源分配图如下图所示。

资源分配图

​ (1)请检查T0时刻的安全性。

​ 解:检查T0时刻的安全性,其实际就是使用安全性算法检测T0时刻OS的安全状态。我们通过安全性检查对T0时刻的资源分配状况进行分析:首先执行算法步骤1,因为此时所有的进程Finish全为false,且进程P1与P3的需求向量都小于Work向量,因此我们选取进程P1(选取哪个进程皆可,安全序列不唯一),并依次执行步骤2、3,完成后Work={5, 3, 2},转为执行步骤1…

​ 经过安全性算法分析,分析过程如下图所示,OS在T0时刻存在一个安全序列{P1, P3, P4, P2, P0},故系统是安全的。

资源分配图

​ (2)在T0时刻,进程P0发出请求向量Request0(0, 3, 0),OS是否可以把资源分配给进程P0?

​ 解:P0请求资源,系统按照银行家算法进行检查:

​ ①Request0(0, 3, 0) <=Need0(7, 4, 3);

​ ②Request0(0, 3, 0)<=Available(3, 3, 2);

​ ③系统先假定可为进程P0分配资源,并修改相关数据:

​ Available = Available(3, 3, 2) - Request0(0, 3, 0) = (3, 0, 2);

​ Allocation0= Allocation0(0, 1, 0) + Request0(0, 3, 0) = (0, 4, 0);

​ Need0 = Need0(7, 4, 3) - Request0(0, 3, 0) = (7, 1, 3);

​ 当前资源分配表如下所示:

资源分配图

​ ④进行安全性检查,可用资源Available(3, 0, 2)已经不能满足任何进程的需要,故系统进入不安全状态,进程P0请求的资源不能分配。

5.总结

​ 银行家算法是一个非常经典的算法,也是死锁避免算法中的最具代表性的算法,其思想是非常值得我们学习的。死锁处理的四种方法:预防死锁、避免死锁、检测死锁、解除死锁。其中预防死锁最为复杂,需要为OS设定各种定律、准则,较难实现,且较为影响系统的性能,最主要的就是并发效率下降;避免死锁可以让OS不必遵循特定的准则,因此给OS施加的限制较小,设计者也希望能通过此获得更好的系统性能,但是因为需要进程提前申明所需的最大资源,因此进程在进入系统前需要先对自身所需资源的进行一个最坏情况下的预估(要满足运行,必定是>=实际需要的,否则因为银行家算法在第一步就给卡死就非常冤了),但是这样,也必定会影响系统的并发,进而影响系统性能;死锁的检测和解除,是采用的“鸵鸟策略”,我不关心你会不会发生死锁,OS定时进行死锁检测,发现后进行解除,通过这种方式,反而可以获得更好的并发,因为在银行家算法中,许多情况下,不安全状态并不一定会转换为死锁。

​ 但是OS选取何种方法,也是需要根据自身设计的一个目的来选定,没有哪个方法一定比哪个好。

​ 本算法对应的Java实现请参考这篇博文。


​ 又到了分隔线以下,本文到此就结束了,本文内容全部都是由博主自己进行整理并结合自身的理解进行总结,如果有什么错误,还请批评指正。

​ 如有兴趣,还可以查看我的其他几篇博客,都是OS的干货,原创不易,喜欢的话还请点赞、评论加关注_

​ 操作系统武功修炼心法

这篇关于避免死锁-----银行家算法详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/631277

相关文章

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

Spring AI使用tool Calling和MCP的示例详解

《SpringAI使用toolCalling和MCP的示例详解》SpringAI1.0.0.M6引入ToolCalling与MCP协议,提升AI与工具交互的扩展性与标准化,支持信息检索、行动执行等... 目录深入探索 Spring AI聊天接口示例Function CallingMCPSTDIOSSE结束语

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编