2.4_3 死锁的处理策略——避免死锁

文章目录

  • 2.4_3 死锁的处理策略——避免死锁
    • (一)什么是安全序列
    • (二)安全序列、不安全状态、死锁的联系
    • (三)银行家算法
  • 总结

2.4_3 死锁的处理策略——避免死锁

image-20240309132537751

  银行家算法是“避免死锁”策略的最著名的一个算法。

(一)什么是安全序列

  你是一位成功的银行家,手里掌握着100个亿的资金。

  有三个企业想找你贷款,分别是企业B、企业A、企业T,为描述方便,简称BAT。

  B表示:“我最多会跟你借70亿。”

  A表示:“我最多会跟你借40亿。”

  T表示:“我最多会跟你借50亿。”

  但是,有个规矩:如果你借给企业的钱总数达不到企业提出的最大要求,那么不管你之前给企业借了多少钱,那些钱都拿不回来了。

  刚开始,BAT三个企业分别从你这借了20、10、30亿。

image-20240309133835637

  显然,你手上还有40亿。


情况1

  手里还有40亿。

  此时,B还想借30亿,你敢借吗?假如我们借给他了,那么情况如下表。

image-20240309133954998

  由于刚刚手上还有40亿,且借给了B企业30亿,那么手上还有10亿。

  而由上表所示,如果BAT任何一个公司再借20亿,那么自己手上的10亿就满足不了他们的请求。又因为“如果你借给企业的钱总数达不到企业提出的最大要求,那么不管你之前给企业借了多少钱,那些钱都拿不回来了”的这个规矩,所以你最终借出去的所有钱都收不回来了。

  因此,在刚刚B向你再借30亿的时候,你就不应该借给他。即,给B借30亿是不安全的。


情况2

  手里还有40亿。

  此时,A还想借20亿,你敢借吗?假如我们借给他了,那么情况如下表。

image-20240309134349226

  由于刚刚手上还有40亿,且借给了A企业20亿,那么手上还有20亿。

  接下来,情况就比较乐观了,这个局就不是一个死局了。

  1.你可以先把20亿全部借给T,等T把钱全部还回来,手里就会有50亿,再把这些钱全部借给B,B还钱后就会有70亿,最后再借给A。

  2.或者,先借给A企业10亿,等A还钱,手里就有了50亿,再借给T企业20亿,等T还钱,手里就有了80亿,最后再借给B。

  即:“A还想再借20亿”是安全的,并且再借给A后,按照T ---> B ---> A的顺序借钱是可以的,而按照A ---> T ---> B的顺序借钱也是可以的。

(二)安全序列、不安全状态、死锁的联系

  经过分析,我们发现:有的资源请求是不能答应的,而有的资源请求是可以答应的。

不安全

image-20240309133954998

  给B借30亿是不安全的。借出之后手里只剩10亿,如果接下来BAT任何一个企业再借20亿,那么任何一个企业都得不到满足。就成为一个死局。

安全

image-20240309134349226

  给A借20亿是安全的,因为存在T ---> B ---> A这样的安全序列

  所谓安全序列,就是指如果系统按照这种序列分配资源,则每个进程都能顺利完成。只要能找出一个安全序列,系统就是安全状态。当然,安全序列可能有多个

  如果分配了资源以后,系统中找不出任何一个安全序列,系统就进入了不安全状态。这就意味着之后可能所有进程都无法顺利的执行下去。当然,如果有进程提前归还了一些资源,那系统也有可能重新回到安全状态,不过我们在分配资源之前总是要考虑到最坏的情况。

  如果系统处于安全状态(即,至少存在一个安全序列),就一定不会发生死锁。如果系统进入不安全状态(即,找不到任何一个安全序列),就可能发生死锁(处于不安全状态未必就是发生了死锁,但发生死锁时一定是在不安全状态)。

  因此可以在资源分配之前预先判断这次分配是否会导致系统进入不安全状态,以此决定是否答应资源分配请求。这也是“银行家算法”的核心思想。

(三)银行家算法

  银行家算法是荷兰学者Dijkstra为银行系统设计的,以确保银行在发放现金贷款时,不会发生不能满足所有客户需要的情况。后来该算法被用在操作系统中,用于避免死锁

  接下来思考一下,怎么把这种用于银行系统的算法,运用到操作系统的避免死锁上面?

  核心思想:在进程提出资源申请时,先预判此次分配是否会导致系统进入不安全状态。如果会进入不安全状态,就暂时不答应这种请求,让该进程先阻塞等待。

  思考:BAT的例子中,只有一种类型的资源——钱。但是在计算机系统中会有多种多样的资源(打印机、扫描仪、摄像头……),应该怎么把算法拓展为多种资源的情况呢?

  其实很简单,我们只需要把一维的数字(仅代表钱)拓展为多维的向量。

image-20240309142911667

  比如:系统中有5个进程P0-P4,3种资源R0-R2,初始数量为(10, 5, 7)。则某一时刻的情况可表示如下。

image-20240309142856629

  根据上表,此时已分配了(7, 2, 5),还剩余(3, 3, 2)

image-20240309143011154

  再根据“每个进程最多还需要”的数量,判断此时是否处于安全状态。

  问题:此时系统是否处于安全状态?

  方案:可以尝试着看看能不能找到一个安全序列。

  依次检查剩余可用资源(3, 3, 2)是否能满足各进程的需求。

  可满足P1需求,将P1加入安全队列,并更新剩余可用资源值为(5, 3, 2)

  经过从前到后的检查,首先发现P1进程可以满足。那么,我们优先把剩余资源分配给P1的话,P1是一定可以顺利结束的,而一旦P1顺利结束了,P1就会归还资源。于是,资源数就会增加到(2, 0, 0) + (3, 3, 2) = (5, 3, 2)

  依次检查剩余可用资源(5, 3, 2)是否能满足剩余进程(不包括已加入安全序列的进程,如下图所示)的需求。

  可满足P3需求,将P3加入安全序列,并更新剩余可用资源值为(7, 4, 3)

image-20240309234544230

  经过从前到后的检查(P1已加入安全序列,不检查P1),首先发现P3进程可以满足。那么,如果优先把资源分配给P3,P3一定是可以顺利执行结束的。等P3结束了就会归还资源。于是,资源数就会增加到(2, 1, 1) + (5, 3, 2) = (7, 4, 3)

  依次检查剩余可用资源(7, 4, 3)是否能满足剩余进程(不包括已加入安全序列的进程)的需求……

image-20240310001220590

  以此类推,共五次循环检查即可将5个进程都加入安全序列中,最终可得一个安全序列:{P1, P3, P0, P2, P4}

  该算法称为安全性算法。可以很方便地用代码实现以上流程,每一轮检查都从编号较小的进程开始检查。


  实际做题时可以更快速的得到安全序列。因为实际做题的时候是用笔算的,没必要按照代码逻辑执行的那么严谨。说明如下,

image-20240310001659110

  还是刚才的题。资源总数(10, 5, 7),此时系统剩余可用资源(3, 3, 2)

  如果从手算的视角来观察,经过对比,(3, 3, 2)可以给P1,也可以给P3。因此,可以一并将P1、P3都加入安全序列。同时,计算P1、P3归还资源之后的剩余资源值。更新剩余资源值为(2, 0, 0) + (2, 1, 1) + (3, 3, 2) = (7, 4, 3)

  因为,(3, 3, 2)如果能满足P1,那么待分配给P1,等P1使用完归还资源,这样之后,手上的剩余资源只会比(3, 3, 2)更多。因此一定能继续满足P3的使用。

  所以,当我们对于这种情况进行考虑时,就不需要考虑的这么麻烦。我们只需要考虑,把资源给P1、P3之后的情况,而不需要再机械的遵循代码运行逻辑。

image-20240310013114317

  同理,此时剩余资源(7, 4, 3),可以给P0、可以给P2、也可以给P4。因此,可以一并将P0、P2、P4都加入安全序列。同时,更新剩余资源值。

  于是,5个进程全部加入安全序列,说明此时系统处于安全状态,暂时不可能发生死锁了。


  再举一个“找不到安全序列”的例子。

image-20240310013323931

  首先,经过对比,(3, 3, 2)可满足P1、P3,因此可以把P1、P3加入安全序列。并更新此时剩余资源值为(2, 0, 0) + (2, 1, 1) + (3, 3, 2) = (7, 4, 3)

image-20240310013900356

  继续对比,对于剩下的进程,P0、P2、P4都得不到完全满足(向量中的各个分量,只要有一个得不到满足,就无法满足)。

  于是,无法找到任何一个安全序列。说明此时系统处于不安全状态有可能发生死锁


如何用代码实现银行家算法

  假设系统中有n个进程,m种资源

  每个进程在运行前先声明对各种资源的最大需求数,则可用一个n * m的矩阵(可以用二维数组实现)表示所有进程对各种资源的最大需求数。不妨称之为最大需求矩阵Max。在矩阵中,每个元素Max[i, j] = k表示进程Pi最多需要k个资源Rj

  系统还需要记录“此时已经给每个进程分配了多少资源”。同理,可以使用一个n * m分配矩阵Allocation表示对所有进程的资源分配情况。

  至于每个进程“最多还需要多少资源”,我们只需使用Max - Allocation即可,并同样使用一个二维矩阵保存之。不妨称之为Need矩阵,表示各进程最多还需要多少各类资源。

  此外,还需要记录“系统中剩余资源的数量”。对此,我们使用一个一维数组即可。可以使用一个长度为m的一维数组Available表示当前系统中还有多少可用资源。

  当某进程Pi向系统申请资源时,可用一个长度为m的一维数组Requesti表示本次申请的各种资源的数量。

image-20240310021048279

  各个数据结构都已设置好,接下来考虑如何进行操作。

  可用银行家算法预判本次分配是否会导致系统进入不安全状态:

  1.如果Requesti[j] <= Need[i, j](0 ≤ j ≤ m),便转向2,否则认为出错(因为它本次申请的资源数量超过了它“最多还需要”的资源数量)。

  2.如果Requesti[j] <= Available[j](0 ≤ j ≤ m),便转向3,否则表示尚无足够资源,Pi必须等待。

  3.系统试探着把资源分配给进程Pi,并修改相应的数据(并非真的分配,修改数值只是为了做预判,看看是否安全,最终确认安全了才会开始分配资源)。

  Available = Available - Requesti

  Allocation[i, j] = Allocation[i, j] + Requesti[j]

  Need[i, j] = Need[i, j] - Requesti[j]

  4.操作系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。若安全,才正式分配;否则,恢复相应数据,让进程阻塞等待。

  所谓的“安全性算法”,就是逐个对比,看看当前剩余资源能否满足其中某个进程的最大需求。若有一个可满足的,则将该进程加入安全序列,并使得此进程归还所有它持有的资源。如果所有进程都不能满足,则此时是不安全状态。

总结

数据结构的设置

  1.长度为m的一维数组Available表示还有多少可用资源;

  2.n * m矩阵Max表示各进程对资源的最大需求数;

  3.n * m矩阵Allocation表示已经给各进程分配了多少资源;

  4.Max - Allocation = Need矩阵表示各进程最多还需要多少资源;

  5.用长度为m的一维数组Requesti表示进程此次申请的各种资源数。

银行家算法步骤

  1.检查此次申请是否超过了之前声明的最大需求数;

  2.检查此时系统剩余的可用资源是否还能满足这次请求;

  3.试探着分配,更改各数据结构;

  4.用安全性算法检查此次分配是否会导致系统进入不安全状态。

安全性算法步骤

  检查当前的剩余可用资源是否能满足某个进程的最大需求,如果可以,就把该进程加入安全序列,并把该进程持有的资源全部回收。

  不断重复上述过程,看最终是否能让所有进程都加入安全序列。


  注意:系统处于不安全状态未必死锁,但死锁时一定处于不安全状态。系统处于安全状态一定不会死锁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/444489.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【sgExcelGrid】自定义组件:简单模拟Excel表格拖拽、选中单元格、横行、纵列、拖拽圈选等操作

特性&#xff1a; 可以自定义拖拽过表格可以点击某个表格&#xff0c;拖拽右下角小正方形进行任意方向选取单元格支持选中某一行、列支持监听selectedGrids、selectedDatas事件获取选中项的DOM对象和数据数组支持props自定义显示label字段别名 sgExcelGrid源码 <template&g…

LLM长上下文外推方法

现在的LLM都集中在卷上下文长度了&#xff0c;最新的Claude3已经支持200K的上下文&#xff0c;见&#xff1a;cost-context。下面是一些提升LLM长度外推能力的方法总结&#xff1a; 数据工程 符尧大佬的最新工作&#xff1a;Data Engineering for Scaling Language Models to …

计算机网络——计算机网络的性能

计算机网络——计算机网络的性能 速率带宽吞吐量时延时延宽带积往返时间RTT利用率信道利用率网络利用率 我们今天来看看计算机网络的性能。 速率 速率这个很简单&#xff0c;就是数据的传送速率&#xff0c;也称为数据率&#xff0c;或者比特率&#xff0c;单位为bit/s&#…

C语言——强制类型转化

强制类型转化的作用 C语言中的强制类型转换是一种将一个数据类型转换为另一个数据类型的操作。它可以通过显式地指定要转换的数据类型来实现。强制类型转换可以用于以下几种情况&#xff1a; 改变变量的数据类型&#xff1a;当需要将一个变量的数据类型从一种类型转换为另一种…

【libwebrtc】基于m114

libwebrtc A C++ wrapper for binary release, mainly used for flutter-webrtc desktop (windows, linux, embedded).是 基于m114版本的webrtc 最新(20240309 ) 的是m122了。官方给出的构建过程 .gclient 文件 solutions = [{"name" : src,"url

域名交易系统已测试可正常使用免授权带后台

域名交易系统已测试可正常使用免授权带后台 下载地址&#xff1a;迅雷云盘

python处理geojson为本地shp文件

一.成果展示 二.环境 我是在Anaconda下的jupyter notebook完成代码的编写&#xff0c;下面是我对应的版本号&#xff0c;我建议大家在这个环境下编写&#xff0c;因为在下载gdal等包的时候会更方便。 二.参考网站 osgeo.osr module — GDAL documentation osgeo.ogr module …

链表基础知识详解

链表基础知识详解 一、链表是什么&#xff1f;1.链表的定义2.链表的组成3.链表的优缺点4.链表的特点 二、链表的基本操作1.链表的建立2.链表的删除3.链表的查找4.链表函数 一、链表是什么&#xff1f; 1.链表的定义 链表是一种物理存储单元上非连续、非顺序的存储结构&#xf…

SQLite3中的callback回调函数注意的细节

调用 sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void *data, char **errmsg)该例程提供了一个执行 SQL 命令的快捷方式&#xff0c; SQL 命令由 sql 参数提供&#xff0c;可以由多个 SQL 命令组成。 在这里&#xff0c; 第一个参数 sqlite3 是打开的数据库对…

Go语言数据结构(二)堆/优先队列

文章目录 1. container中定义的heap2. heap的使用示例3. 刷lc应用堆的示例 更多内容以及其他Go常用数据结构的实现在这里&#xff0c;感谢Star&#xff1a;https://github.com/acezsq/Data_Structure_Golang 1. container中定义的heap 在golang中的"container/heap"…

使用yarn创建vite+vue3electron多端运行

文章目录 第一步 使用yarn创建vite+vue3项目遇到创建报错看第二步 引入electron第三步 创建main.js在electron下面的main.js写入下面代码第四步 安装同时运行多条命令npm包&&修改package.json文件npm包增加一条electron运行脚本命令效果图第一步 使用yarn创建vite+vue3…

T-RAG = RAG + Fine-Tuning + Entity Detection

原文地址&#xff1a;T-RAG RAG Fine-Tuning Entity Detection T-RAG 方法的前提是将 RAG 架构与开源微调的 LLM 和实体树向量数据库相结合。重点是上下文检索。 2024 年 2 月 15 日 介绍 大型语言模型 (LLM) 越来越多地应用于各个领域&#xff0c;包括对私营企业文档的问答…

Pb量级超大容量光存储

近日&#xff0c;中国科学院上海光学精密机械研究所&#xff08;以下简称“上海光机所”&#xff09;与上海理工大学等科研单位合作&#xff0c;在超大容量三维超分辨光存储研究中取得突破性进展。研究团队利用国际首创的双光束调控聚集诱导发光超分辨光存储技术&#xff0c;实…

docker-compose这下会用了吗?

概要 默认的模板文件是 docker-compose.yml&#xff0c;其中定义的每个服务可以通过 image 指令指定镜像或 build 指令&#xff08;需要 Dockerfile&#xff09;来自动构建。 注意如果使用 build 指令&#xff0c;在 Dockerfile 中设置的选项(例如&#xff1a;CMD, EXPOSE, V…

Linux 学习(持续更新。。。)

wc命令 命令直接执行&#xff0c;输出包含四项&#xff0c;分别代表&#xff1a;行数、字数、字节数、文件。 例子:编译下列代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #inclu…

报错Importing ArkTS files to JS and TS files is not allowed. <etsLint>

ts文件并不支持导入ets文件&#xff0c;为了方便开发应用卡片&#xff0c;entryformAbility创建的时候默认是ts文件&#xff0c;这里只需要把ts文件改成ets便可以轻松的导入所需要的ets即可 我创建了一个鸿蒙开发的交流群&#xff0c;喜欢的鸿蒙朋友可以扫码或者写群号&#xf…

【编译原理】1、python 实现一个 JSON parser:lex 词法分析、parser 句法分析

文章目录 一、实现 JSON lexer&#xff08;词法解析器&#xff09;二、lex 词法分析2.1 lex string 解析2.2 lex number 解析2.3 lex bool 和 null 解析 三、syntax parser 句法分析3.1 parse array 解析数组3.2 parse object 解析对象 四、封装接口 一、实现 JSON lexer&#…

时间感知自适应RAG(TA-ARE)

原文地址&#xff1a;Time-Aware Adaptive RAG (TA-ARE) 2024 年 3 月 1 日 介绍 随着大型语言模型&#xff08;LLM&#xff09;的出现&#xff0c;出现了新兴能力的概念。前提或假设是LLMs具有隐藏的和未知的能力&#xff0c;等待被发现。企业家们渴望在LLMs中发现一些无人知晓…

Linux网络基础2之协议

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 目录 1.协议 1.序列化与反序列换 2.协议定制 二…

LLM实施的五个阶段

原文地址&#xff1a;Five Stages Of LLM Implementation 大型语言模型显着提高了对话式人工智能系统的能力&#xff0c;实现了更自然和上下文感知的交互。这导致各个行业越来越多地采用人工智能驱动的聊天机器人和虚拟助手。 2024 年 2 月 20 日 介绍 从LLMs的市场采用情况可以…