什么是死锁
如果一组进程中的每一个进程都在等待 仅由该组进程中的其他进程才能引发的事件(就是每一个进程都在等待其他进程完成他们的任务 这时没有一个进程可以完成各自的任务)
产生死锁的必要条件
(必要条件就是这些条件都满足的情况下才可能发生死锁)
互斥条件:有类似临界资源的情况 有进程获得了进程,其他进程可能无法获得资源
请求和保持条件:进程在获取了至少一个资源的情况下,有提出了新的资源请求 而请求的这个新资源又正好被其他进程占有 并且该进程也不会因为自己获取不到新的资源而释放已有资源
不可抢占条件:进程已经获得的资源在位使用完之前不能被其他资源获取
循环等待条件:即形成一个环 a1缺a2已占有的资源 a2缺a3已占用的资源 a3缺a4已占用的资源 a4缺a1已占有的资源
破坏死锁的方法
破坏“请求和保持条件”条件:
当一个进程在请求资源时该进程不能持有不可抢占资源 实现这种情况的方法有两种
1.一次性申请完所有资源 如果有一个资源无法申请则该进程挂起 其他资源都不可申请
优点:简单 易行 安全
缺点:严重降低了资源利用率
2.可以先申请初期运行需要的资源 利用完之后就直接释放掉 再申请后面需要用到的资源 特点就是初期要什么资源就申请什么 用完就立马释放 也就是把一个进程的任务分成了几个部分
**破坏”不可抢占“条件:**就是变成可抢占就行了
破坏”循环等待“条件:
给每个资源赋予唯一的序号 例如磁带驱动器 = 1,硬盘驱动器 = 2,打印机 = 5 每个进程需要按序号递增的顺序请求资源 例如 某进程想申请 磁带驱动器,硬盘驱动器,打印机三个资源 那么他必须先申请磁带驱动器 再申请硬盘驱动器和打印机 如果该进程已拥有硬盘驱动器 想申请磁带驱动器 则不符合规则 需要释放掉硬盘驱动器 再申请磁带驱动器(已请求到较高序号的资源后 想申请序号低的资源时 必须释放掉所有具有相同和更高序号的资源)
银行家算法(避免死锁)
为什么叫银行家算法
该算法最初是为银行系统设计的 已确保银行在发放现金贷款时 不会发生不能满足所有客户的需要的情况
银行家算法四个数据结构
可利用资源向量Avaliable:初始值是系统中所配置的该类全部可用资源的数目 数值随该类资源的分配和回收而动态的改变 如果Avaliable[j] = K则表示系统中现有Rj类资源K个 就是目前系统环境中可以用的该类资源有多少 就是Work
最大需求矩阵Max:定义了系统中n个进程中的每个进程对m类资源的最大需求 如果Max[i,j] = K 则表示进程i需要Rj类资源的最大数目为K 就是这个进程总共需要的该类资源数量
分配矩阵Allocation:定义了系统每一类资源当前已分配给每一进程的资源数 如果Allocation[i,j] = K则表示进程i当前已分的Rj类资源的数目为K 就是这个进程目前获得了该类资源的数量
需求矩阵Need:定义了每一个进程还需要的各类资源数 如果Need[i,j] = K则表示进程i还需要Rj类资源K个 就是这个进程除去已经分配该类的资源 还需要的该类资源
Need[ i , j ] = Max[ i , j ] - Allocation[ i , j ] 还需要的该类资源 = 总共需要的-已经获得的
Requesti 是Pi 的请求向量
Requesti [j] = K表示进程Pi需要K个Rj类型的资源
当Pi发出请求时 就会执行银行家算法
银行家算法过程
就是如果系统发出来请求Request的时候
1.如果Requesti [ j ]<=Need[ i , j ]则意思时这次发出请求的该资源数量小于该进程还需要该类资源的数量 就表明这次请求没有错 如果本次请求数量大于还需求的数量就说明这次请求就不对
2.如果Requesti [ j ]<=Available[ j ]则意思是本次请求的该类资源低于目前系统可以提供的该类资源
3.系统试着把资源分配给进程Pi 数据就会发生动态变化:
Avaliable(Work)[ j ] = Available(Work)[ j ] - Request[ j ] 因为提供了请求 所有可用资源要减少
Allocation[ i , j ] = Allocation[ i , j] + Rrquesti [ j ] 已被分配资源增加
Need[ i, j ] = Need[ i , j ] - Requesti [ j ] 还需要资源减少
4.系统执行安全性算法 检查此次资源分配后系统是否处于安全状态 若安全 才正式将资源分配给进程Pi 完成本次分配 否则本次作废 恢复为原来的样子
安全性算法
工作向量Work 表示系统可提供给进程继续运行所需要的各类资源数目
Finish:表示系统是否有足够的资源分配给进程 如果有则为true 没有则为false
在执行安全算法开始
这里就重新建一个表
Work = Available 而Available = 在初始资源 - 其他所有进程已分配的资源
Work = 初始资源 - Need[1-n];
所有Finish[ i ] = false
从进程中从上到下找到一个满足下述条件的进程
1.Finish[ i ] = false
2.Need[ i , j ] <= Work[ j ]; 若找到执行步骤3 没找到执行步骤4
3.当进程Pi 获取到资源后 就执行 执行完毕后释放出资源
Work[ j ] = Work[ j ] + Allocation[ i , j ]
Finish[ i ] = true
跳转到第2步
3.如果所有进程Finish[ i ] = true都满足 则表示系统处于安全状态 否则处于不安全状态
银行家算法例题
假设系统中有五个进程P0,P1,P2,P3,P4,P5和三类资源A(初始数量10),资源B(初始数量5),资源C(初始数量7)
(1)在T0时刻的安全性?
T0时刻如图所示
初始值A(10)B(5)C(7) | Max | Allocation |
---|---|---|
资源类型 | A B C | A B C |
进程 | ------------- | ------------- |
P0 | 7 5 3 | 0 1 0 |
P1 | 3 2 2 | 2 0 0 |
P2 | 9 0 2 | 3 0 2 |
P3 | 2 2 2 | 2 1 1 |
P4 | 4 3 3 | 0 0 2 |
根据Need = Max - Allocation 写出Need列
则绘制新表
初始值A(10)B(5)C(7) | Max | Allocation | Need |
---|---|---|---|
资源类型 | A B C | A B C | A B C |
进程 | ------------- | ------------- | ------------- |
P0 | 7 5 3 | 0 1 0 | 7 4 3 |
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 |
先判断没有Need为负数 进程正常
再计算出Work在T0时刻的值
Work(A) = 初始值(A) - Allocation(A) = 3
Work(B) = 初始值(B) - Allocation(B) = 3
Work(C) = 初始值© - Allocation© = 2
Work = 3 3 2
然后我们在Need栏从上往下找 Work能满足 Work>=Need 因为Work是减去了已经分配给其他进程资源空余出来的 我们先找到了P1适合
则创建新表:
初始值A(10)B(5)C(7) | Work | Need | Allocation | Work+Allocation | Finish |
---|---|---|---|---|---|
资源类型 | A B C | A B C | A B C | A B C | A B C |
进程 | ------------- | ------------- | ------------- | ------------- | ------------- |
P1 | 3 3 2 | 1 2 2 | 2 0 0 | 5 3 2 | true |
work在运行P1之前是3 3 2
Need是P1还需要的资源数
Allocation是P1已经被分配的资源数
Work+Allocation是P1在执行结束之后Work的值 因为执行结束 所以向系统返回以前已经被分配的资源
Finish是可以安全执行
后面的就类似了
初始值A(10)B(5)C(7) | Work | Need | Allocation | Work+Allocation | Finish |
---|---|---|---|---|---|
资源类型 | A B C | A B C | A B C | A B C | A B C |
进程 | ------------- | ------------- | ------------- | ------------- | ------------- |
P1 | 3 3 2 | 1 2 2 | 2 0 0 | 5 3 2 | true |
P3 | 5 3 2 | 0 1 1 | 2 1 1 | 7 4 3 | true |
P4 | 7 4 3 | 4 3 1 | 0 0 2 | 7 4 5 | true |
P2 | 7 4 5 | 7 4 3 | 0 1 0 | 7 5 5 | true |
P0 | 7 5 5 | 6 0 0 | 3 0 2 | 10 5 7 | true |
可得知T0时刻的安全序列是P1,P3,P4,P2,P0
(2)T0时刻P1发出请求 Request1 (1,0,2)
先按照银行家算法进行检查
Request1 (1,0,2)<=Need1 (1,2,2);请求没有超过该进程的需求 是一个正常的请求
Request1 (1,0,2)<=Work1 (3,3,2);请求没有超过系统此时所能提供的资源数量 可以提供
则更改
初始值A(10)B(5)C(7) | Work | Need | Allocation | Work+Allocation | Finish |
---|---|---|---|---|---|
资源类型 | A B C | A B C | A B C | A B C | A B C |
进程 | ------------- | ------------- | ------------- | ------------- | ------------- |
P1 | 2 3 0 | 0 2 0 | 3 0 2 | 5 3 2 | true |
需要更改
先更改Allocation[ i , j ] = Allocation[ i , j] + Rrquesti [ j ] 因为请求了更多的资源 所以系统已经分配给P1的资源就增加了
再更改Need[ i, j ] = Need[ i , j ] - Requesti [ j ] 因为已经分配的资源增加 所以还需要的资源就减少了
最后更改Work[ j ] = Work[ j ] - Request[ j ] 因为Allocation做了变更 已经分配的资源增加了 所以系统目前能分配给进程的资源就减少了
然后还必须从P1开始
后面就和前面一样了
(3)T0时刻P4发出请求 Request4 (3,3,0)
Request4 (3,3,0)<=Need1 (4,3,1);请求没有超过该进程的需求 是一个正常的请求
Request4 (3,3,0)>Work1 (2,3,0);请求超过系统此时所能提供的资源数量 让P4等待
(4)T0时刻P0发出请求 Request0 (0,2,0)
Request0 (0,2,0)<=Need0 (7,4,3);请求没有超过该进程的需求 是一个正常的请求
Request0 (0,2,0)<=Work0 (2,3,0);请求没有超过系统此时所能提供的资源数量 可以提供
初始值A(10)B(5)C(7) | Work | Need | Allocation | Work+Allocation | Finish |
---|---|---|---|---|---|
资源类型 | A B C | A B C | A B C | A B C | A B C |
进程 | ------------- | ------------- | ------------- | ------------- | ------------- |
P0 | 2 1 0 | 7 2 3 | 0 3 0 | x | f |
此时会发现 Work变成了2 1 0无法满足任何进程的需求了 包括P0
如果题目是在什么基础上P4:Request(2,0,1),能否分配这种 那就在上面那个表更新之后的基础上再看看Request是否可以
资源分配图
圈圈代表一个进程 方框代表一类资源 方框中的圆圈代表一类资源中的一个资源 也就是这类资源的数量
表示P1想要请求一个R2资源
P2想要请求一个R1资源
R1提供了两个资源给P1 一个资源给P2
R2提供了一个资源给P2
资源分配图的简化
像图中 P1可以获取到一个R2资源 说明他可以先运行结束
所以可以擦去他边上的箭头