操作系统(6) 死锁和饥饿
1.死锁
1.1 死锁原理
当一组进程中每个进程都在等待某个事件(所请求的资源被释放),而只有在这组进程中的其他阻塞进程才能触发该事件,就称该组进程触发了死锁。
死锁涉及到了两个或者多个进程之间的资源需求冲突。
死锁原因:进程推进顺序不当、竞争资源
例子:
路线解读:
1.Q进程一次性完成所有工作,请求B再请求A,得到资源后执行代码并且马上释放,资源A与B均释放后进程P才获得CPU执行代码,此时由于进程组中没有其它进程需要申请资源A和资源B,此时不会触发死锁
2.Q进程请求B再请求A,释放资源B,完成一部分工作后超时,进程P获得CPU执行代码,请求资源A,但此时资源A被Q进程占用,资源A阻塞,时间片超时后Q进程获得CPU,从断点处继续执行,释放资源A,进程P获得CPU执行代码,此时资源A可被访问,进程P继续完成工作
3.进程Q请求资源B,并且获得持有资源B,给资源B上锁,此时时间片超时,中断后进程P获得CPU,进程P申请资源A,并且获得持有资源A,给资源A上锁,此时进入了敏感区域,如果像上述的描述一样,下一步,进程Q持有资源B,但是申请A,申请A而不得,因而阻塞,等待资源A被释放,进程P持有资源A,但是申请B,申请B而不得,因而阻塞,等待资源B被释放,此时就产生了一个逻辑,进程Q需要进程P继续执行才能获得被释放的资源A,而进程P需要进程Q继续执行才能获得被释放的资源B,两个进程互相等待,死锁。
修改请求和释放资源的次序可以避免死锁:进程P(请求A,释放A,请求B,释放B),进程Q(请求B,请求A,释放B,释放A) ,此时进程P不要求同时拥有资源A和资源B,这样请求后的时序图如:
1.2 可重用资源
两类资源:可重用资源和可消耗资源
可重用资源:可重复使用、互斥使用,如:CPU、虚拟内存、磁盘等,还可以细分为不可剥夺资源:打印机、磁带机等,这些资源在使用过程中不能被剥夺,否则会导致失败。
如果竞争不可剥夺资源可能会导致死锁。
为什么死锁不会涉及 虚拟内存或磁盘?答:(个人理解,不一定对)因为死锁有四个必要条件,其中一个必要条件是不可抢占,而虚拟内存或磁盘的资源性质不是不可剥夺资源,不满足该条件,因此不涉及死锁。(这种资源由系统统一管理,由不得进程霸占)
1.3 可消耗资源
可消耗资源:可被创建(生产)和销毁(消费)的资源。如信号、消息、缓冲数等
竞争可消耗资源也可能导致死锁,例如进程P1、P2都要产生一个消息,并且接收对方一个消息时:
①假设每个进程都先产生消息、再接收消息时,并不会产生死锁
②但若必须先接收(被阻塞直到收到信息时才执行)再产生时,就会发生死锁。
1.4 资源分配图
有向图,用来描述资源和进程状态
- 进程节点:P
- 资源节点:R。一个圆点表示一个资源实例
- 请求边:进程->资源。Pi->Rj
- 分配边:资源->进程。Rj->Pi
如图所示,该进程与资源状态是否产生了死锁?
答:我们根据化简法来解这道题,首先需要知道在资源分配图上,进程的阻塞是如何表示的:应该是进程指向了一个资源,而该资源当前不可用的时候,就是阻塞的,由图可知,P2是阻塞的,而P1申请的R2资源是可用的,因此没有阻塞,因此我们可以消去P1的请求边和分配边,当P1的请求边和分配边都消去之后,P2就不是阻塞的了,这时候所有进程节点都孤立。
如果产生了死锁,那么画出来的资源分配图中一定会有环路
但有环路时,不一定有死锁,要看是否所有进程都阻塞,有些进程在环外的与环内活动无关,此时当环外进程执行完毕后,资源释放后死锁即解除。
1.5 死锁四个必要条件
死锁时,四个必要条件同时成立。某一个或几个必要条件成立时并未进入死锁状态
互斥:需要等待的是需要互斥访问的资源
占有且等待:进程申请资源而阻塞等待时,不释放(继续占有)已分配资源
不可抢占:进程已占用的资源未使用完之前不可强行剥夺(抢占),只能由进程资源释放
循环等待:进程间形成一个等待资源的循环链
2.死锁的三种处理方法
①死锁预防:破坏四个必要条件之一
②死锁避免:不破坏必要条件,允许进程动态申请资源,但检查资源分配状态,以避免可能导致的死锁
③死锁检测和恢复:检查系统是否已死锁、哪些进程和资源涉及死锁,并撤销死锁进程或剥夺资源以摆脱死锁
④忽略死锁(鸵鸟策略):假设死锁不会发生。
2.1 死锁预防
①破坏互斥条件:互斥条件不能被破坏
②破坏占有且等待条件:
资源静态分配法:进程运行前,一次性分配所有需要的资源。若有某个资源不能满足,那么就全部不分配。进程等待直到所有的资源都是可用的。该方法可能引起进程饥饿,资源利用率比较低,进程可能事先不知道资源列表。
③破坏不可抢占条件:
- 进程申请新资源被阻塞时,必须(主动)释放已占用的资源。本进程需要时才重新申请。
- OS具有权限剥夺低优先级进程的资源给高优先级进程
④破坏循环等待条件:
资源有序分配法:系统内每个资源一个编号,各进程必须严格按照编号递增的顺序申请资源
一 次性分配所有资源的方法破坏的是死锁四个 必要条件中的 (B)。A. 互斥 B. 占有且等待C. 不可抢占 D. 循环等待某银行的电子转账系统的业务流程是:先对转出方和 转入方的账户进行加锁,然后转账,最后对转出方和转 入方的账户进行解锁。不采取措施时是否会死锁?答:会死锁,比如说两个账户同时给对方转账时。当同时转账时,系统中的两个进程就会同时需要对甲账户加锁,乙账户加锁,最坏的情况就是进程1已经对甲账户加锁,将要对乙账户加锁的时候,进程2对乙账户加锁了,此时进程1不满足转账条件,阻塞而且等待,进程2也不满足转账条件,阻塞而且等待。死锁。
2.2 死锁避免
系统允许进程动态申请资源。在分配资源之前,先计算资源分配的安全性。若此次分配可能导致死锁,则暂不分配,该进程等待。
两种死锁避免方法:
进程启动拒绝: 如果一个进程的资源最大需求总量会导致死锁,则不启动此新进程
设系统中有n个进程和m种不同类型的资源
定义以下向量和矩阵:n-进程数,m-资源类型数
- 资源总量,R=(R1,R2...Rm)
- 可用资源,V=(V1,V2...Vm)
- 最大需求矩阵 C:NXM的矩阵,C[i,j] = k,表示进程i需要j类型的资源为k个
- 已分配矩阵 A:NXM的矩阵,A[i,j]=k,表示进程i已经分配到了j类型的资源k个
有以下关系成立:
1.Rj = Vj+∑Aij,所有资源,可用或已分配
2.Cij <= Rj,每个进程对一种资源的需求量不能超过系统中该资源的总量
3.进程的资源已分配量不能超过其事先声明的最大需求量
当系统的资源总量能够满足“所有进程的最大需求量加上新进程Pn+1的最大需求量时”,才启动新进程Pn+1。
例如:R=(7,6,5,8),C=((4,1,1,3),(0,3,1,2),(3,2,3,2)),问下一个进程的最大需求量满足什么条件才能启动?
首先对需求矩阵按列求和,得到新向量,也即需求向量c = (7,6,5,7), 用R-c=(0,0,0,1),因此当进程的最大需求量为(0,0,0,0)或者(0,0,0,1)时,才能够启动该进程
资源分配拒绝:如果一个进程提出的某次资源请求会导致死锁,则不允许此次分配。
银行家算法:分配资源前,先计算此次分配是否会导致系统处于不安全状态。若安全则分配,否则不分配
安全状态:存在一个由所有进程(P1,P2,...,Pn)构成的安全序列(如P3,P1,P4,...),如果系统按照这个顺序为每个进程分配所需要的资源,直至该进程声明的最大资源需求量,则可使每个进程都运行完
不安全状态:系统中不存在任何一个安全序列,使得所有进程都能够运行完,这就是不安全状态
例:系统中共有12台磁带机,在T0时刻:
进程 | 最大需求 | 已分配 | 尚需 | 可用 |
P1 | 9 | 2 | 7 | 3 |
P2 | 10 | 5 | 5 | |
P3 | 4 | 2 | 2 |
此时存在一条安全序列,P3->P2->P1.
问:假如P1申请想要一个资源,系统是否会分配?
答:假设系统为P1分配了1个资源,P1仍然不够资源,继续阻塞,此时可用资源为两个,此时这两个资源最好情况下给P3使用,P3使用执行后释放两个资源,此时可用4个资源,扫描进程尚需资源列表,发现无法满足任何一个进程的需要,系统处于不安全状态,于是不分配
注:进程提出资源分配请求后,OS先试探性分配,若处于安全状态才分配,否则暂不分配,进程等待
资源分配算法
解读:首先进程申请资源,对申请资源的数目进行检查,假如说当前申请资源的数目比当初声明所需要的最大资源数目还要大,那么就是出错了,终止分配。接着,如果申请资源的数目比当前可用资源的数目要少,那么该进程必须要等待。假设如果可用资源可以供给给进程使用,那么系统将会试探性地将资源分配给进程,并且执行安全性测试算法,如果安全,那么就分配资源给进程,否则就把数据结构还原。
/*1.安全性检测算法*/#define N 50const int n =N;//进程总数
int available[m];//实际的可用资源bool safe(State s){int currentAvail[m];//系统可用资源数目(临时记录,非真实)process rest[n];//剩余的、未运行完毕的进程集合currentAvail = available;//开始时,currentAvail = 实际的可用的资源rest = {所有进程};bool possible = true;while(possible){for(int i=0;i<n;i++){if(claim[k,*] - alloc[k,*] <= currentAvail[k]){//在rest中(循环)查找一个进程Pk,其资源需求可被满足//如果存在一个满足条件的进程possible = true;currentAvail = currentAvail + alloc[k,*];//认为它能够运行完毕,释放其已经占据的资源rest = rest - {Pk};}}if(possible){continue;}else{break;}}return (rest == NULL);
}
2.3 银行家算法的应用
假定现有资源数量:A(10)、B(5)、C(7),在时刻T0
Cliam A B C |
Allocation A B C |
尚需 Need A B C |
Available A B C |
|
P0 | 7 5 3 | 0 1 0 | 7 4 3 | 3 3 2 |
P1 | 3 2 2 | 2 0 0 | 1 2 2 | |
P2 | 9 0 2 | 3 0 2 | 6 0 0 | |
P3 | 2 2 2 | 2 1 1 | 0 1 1 | |
P4 | 4 3 3 | 0 0 2 | 4 3 1 |
在T0时刻是安全的,可有安全序列:<P1,P3,P2,P4,P0>
首先可用资源分配给P1,P1获取资源后运行完毕,释放资源2 0 0,可用资源变为 -> (5 3 2)
可用资源分配给P3,P3运行完毕后,可用资源变为->(7 4 3)
可用资源分配给P2,运行完毕后,可用资源变为->(10 4 5)
可用资源分配给P4,运行完毕后,可用资源变为->(10 4 7)
可用资源给P0,运行完毕后,可用资源变为->(10 5 7),结束.
在资源分配执行过程中需要执行多次安全性检查,这个是一个不确定因素。
2.4 死锁检测算法
算法结束后,若存在未标记进程(Finish[i]=false),则发生死锁,每个未标记进程都是死锁进程
- Available[m]:系统中每种资源的可用实例数
- Allocation[n,m]:每个进程分得的每种资源实例数
- Request[n,m]:每个进程的资源请求量
- Finish[n]:标记某进程是否能够运行完
/*2.死锁检测算法*/
//params
int Available[m];//系统中每种资源的可用实例数
int Allocation[n][m];//每个进程分得的每种资源实例数
int Request[n][m];//每个进程的资源请求量
int Finish[n];//标记某进程是否能够运行完
int work[m];
int workCanUse = 0;
int deadLockP[n];
int idx = 0;void check(){bool flag = false;for(int i=1;i<=n;i++){if(Finish[i] == false){flag = true;deadLockP[idx++] =i;}}if(flag){cout<<"死锁进程有:";for(int i=0;i<idx;i++){cout<<i<<" ";}cout<<endl;}else{cout<<"系统未发生死锁"<<endl;}
}//1. 初始化:设临时向量 Work = Available 。
//对于进程 i = 1,2, …, n,如果 Allocationi = 0,那么
//Finish[ i ] = true;否则,Finish[ i ] = false
void init(){for(int i=1;i<=m;i++){work[i] = Available[i];workCanUse += Available[i];}bool flag = false;for(int i=1;i<=n;i++){int sum = 0;for(int j=1;j<=m;j++){sum += Allocation[i][j];}if(sum == 0){Finish[i] = true;}else{//寻找一个进程 i ,满足条件://(a) Finish [ i ] == false (b) Requesti Work//(即查找“尚未运行完,且可用资源能满足其请求”的进程)//如果没有这样的进程,转步骤 4.Finish[i] = false;if(sum <= work[i]){//假设Pi 可以运行完并释放其所有资源,则修改向量workCanUse+=sum;Finish[i]=true;flag = true;continue;}}}if(!flag){check();}
}
3.使用资源分配图化简法检测死锁
![](/assets/blank.gif)
4.从死锁中恢复
某系统中仅有 5 个并发进程竞争某类资源, 且都需要 3 个该类资源,那么至少有(11)个 该类资源,才能 保证 系统不会发生死锁解析:5个并发进程,需要3个资源,关键是要找临界状态:发生可能死锁和一定不发生死锁的临界条件是所有进程都获得了距离可运行完毕状态还剩一个资源的时候即为临界状态,再分配多一个资源,则一定不会发生死锁.因此答案为(3-1)*5+1=11某系统有 n 台互斥使用的同类设备,三个并发进程 分别需要 3 、 4 、 5 台设备,可确保系统不发生死锁的 设备数 n 最小是与上题同理:(3-1)+(4-1)+(5-1) +1=10
5.哲学家就餐问题
5.1 基于信号量的解决方案
每把叉子就是一个临界资源。设一信号量数组fork[5],初值均为1
当每个哲学家都拿起一把(左)叉子时,发生死锁
/*3.哲学家就餐问题 - 死锁*/
void philosopher(int i){while(true){think();wait(fork[i]);//拿左叉wait(fork[(i+1) % 5]);//拿右叉eat();signal(fork[(i+1)%5]);//signal的顺序可以任意signal(fork[i]);}
}
/*当所有哲学家同时拿起左叉时,发生死锁*/
/*3.1 使用多一个信号量,实现最多同时允许四个哲学家拿起左叉*/
semaphore room = 4;
semaphore fork[5]={1};void philosopher(int i){while(true){think();wait(room);wait(fork[i]);//拿左叉wait(fork[(i+1) % 5]);//拿右叉eat();signal(fork[(i+1)%5]);//signal的顺序可以任意signal(fork[i]);}
}
/*3.2 奇数号人先拿左叉,偶数号人先拿右叉*/
void philosopher(int i){while(true){think();if(i%2 == 0){wait(fork[(i+1)%5]);wait(fork[i]);}else{wait(fork[i]);wait(fork[(i+1)%5]);}eat();signal(fork[i]);signal(fork[(i+1)%5];}
}
6.Unix的并发机制
6.1 进程间的通信机制
管道、消息、共享内存、信号量(PIC)
6.2 管道
命名管道:用mkfifo()接口创建,可长期存在于磁盘上的FIFO文件,。Is -l时显示的文件类型为p。无关进程通信用。
匿名管道:用pipe()建立的临时的、无路径名的、连接两个父子进程的共享文件。数据单向流动,先入先出,容量有限,进程终止时被销毁
6.3 消息
消息是有类型的一段文本。
每个进程可用msgget()创建一个自己的消息队列,或取得对一个已有消息队列的访问权
msgsnd()向队列放入一条消息,接收者用msgrcv()读取消息,同时该消息从消息队列中删除
6.4 共享内存
先用shmget()创建一个共享内存区
进程用shmat()将其挂载到自己的进程空间,访问之
当不需要时,用shmdt()解除挂接
6.5 信号量
semget()创建信号量集,semctl()获取或设置信号量状态
sem_op()操作信号量:增加/减少信号量值,唤醒/阻塞进程
6.6 信号
信号:通知一个进程发生了异步事件
操作系统(6) 死锁和饥饿相关推荐
- 操作系统-并发:死锁和饥饿
知识架构 本章介绍并发处理中需要解决的两个问题:死锁和饥饿.本章首先讨论死锁的基本原理和饥饿的相关问题:接着分析处理死锁的三种常用方法:预防.检测和避免:然后考虑用于说明同步和死锁的一个经典问题:哲学 ...
- 操作系统——死锁和饥饿
操作系统--死锁和饥饿 转自:https://blog.csdn.net/qq_42192693/article/details/103054682 1.概念 死锁:如果一组进程中的每一个进程都在等待 ...
- 【转载】计算机操作系统出现死锁的原因
目录 1. 死锁的概念以及产生死锁的原因 1.1 死锁的定义 1.2 死锁产生的原因 1) 系统资源的竞争 2) 进程推进顺序非法 3) 死锁产生的必要条件 2. 死锁的处理策略 预防死锁 避免死锁 ...
- 【数据库技术】2PL(两阶段锁)下的死锁与饥饿处理手段
事务处理-2PL下的死锁与饥饿 2PL--2阶段锁存在的问题 一.死锁与等待图 1. 死锁(Deadlock) 2. 等待图(Wait-for graph) 二.死锁的处理手段 1. 死锁预防 2. ...
- 面试问题之操作系统:死锁的四个必要条件和解决办法
面试问题之操作系统:死锁的四个必要条件和解决办法 参考文章: (1)面试问题之操作系统:死锁的四个必要条件和解决办法 (2)https://www.cnblogs.com/yichengming/p/ ...
- 2.4操作系统之死锁详解(预防、避免、检测、解除)+思维导图
文章目录 0.思维导图 1.什么是死锁? 2.死锁.饥饿.死循环的区别 3.死锁产生的四个必要条件 4.什么时候会发生死锁? 5.死锁的处理策略 (1)预防死锁 ① 破坏互斥条件 ② 破坏不可剥夺条件 ...
- 操作系统:线程死锁、饥饿、活锁
1. 死锁 可以认为是两个线程或进程在请求对方占有的资源. 出现以下四种情况会产生死锁: 情况一:相互排斥.一个线程或进程永远占有共享资源,比如,独占该资源. 情况二:循环等待.例如,进程A在等待进程 ...
- 【操作系统】死锁相关知识点
文章目录 1. 死锁基本概念 2. 死锁的四个必要条件 3. 死锁处理方法 3.1 鸵鸟策略 3.2 死锁检测与恢复 3.3 死锁避免 3.4 死锁预防 3.5 死锁处理策略比较 4. 其他相关 4. ...
- 死锁与活锁的区别,死锁与饥饿的区别?
**死锁:**是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 产生死锁的必要条件: 1.互斥条件:所谓互斥就是进程在某一时间 ...
最新文章
- 创建sql自定义的函数及商品分页sql存储过程
- 十万浙企上云 阿里云崛起的最大征候?
- LeetCode第九题—— Palindrome Number(判断回文数)
- 安装Kali Linux操作系统Kali Linux无线网络渗透
- J2Cache 中使用 Lettuce 替代 Jedis 管理 Redis 连接
- Leetcode 剑指 Offer 04. 二维数组中的查找 (每日一题 20210727)
- oracle omf管理 and asm omf
- ElasticSearch学习29_基于Elasticsearch实现搜索推荐
- 关于DG32f103C8T6 不启动的问题-调试可以运行自启动不行
- Linux命令解释之chown
- 在CentOS6.9中搭建HBase
- Tp5.1 图片处理:缩略图+水印(换行显示)
- poj 2996 Help Me with the Game 模拟
- VM12 虚拟机使用桥接模式却连不上网的解决办法
- YLMF OS 发布
- 飞信2008协议抓包(2)
- 离散数学 之 命题公式的主析取合取范式(java实现)
- 林海峰讲的python_python常用模块-------转自林海峰老师
- Solving environment: failed
- 区块链上的中国?2018见分晓
热门文章
- android 繁体输入法,教程:白子繁体中文输入法v2.3.8 Android版
- arcglobe导入三维模型方法
- 北京大学生物信息学笔记-第一周-生物信息学概述
- 1,3,4,6-四-O-乙酰基-2-叠氮-2-脱氧-α-D-吡喃半乳糖/cas:67817-30-5
- HustOJ平台搭建(ubuntu20.04)
- 2020-07-26
- pandas用法大全
- SYSTEMTIME转时间戳
- 云原生爱好者周刊:买个蓝牙打印机实时打印新提交的 PR 吧 | 2022-10-24
- 位运算(按位与、按位或|、按位异或^) 运算规则与实例