系列文章

第一章 操作系统概述
第二章 进程管理之进程描述与控制
第二章 进程管理之进程调度
第二章 进程管理之进程同步

第二章 进程管理 死锁

一组相互竞争系统资源或进行通信的进程间的永久阻塞

2.19 死锁原理

当一组进程中的每个进程都在等待某事件,而只有同组进程中阻塞的其他进程能够促发该事件时,死锁发生

2.19.1 资源分类

  • 可重用资源:一次仅供一个进程使用且不因使用而消耗的资源,如cpu
  • 可消耗资源:可被创建(生产)和销毁(消耗)的资源,如中断、消息

竞争这两种资源时,如果存在循环等待,可能会引起死锁

2.19.2 死锁的条件

  • 必要条件
  • 互斥:一次只有一个进程可以使用一个资源
  • 占有且等待:当进程等待其他资源时继续占有已有的资源
  • 不可抢占:进程不能强行占有其他进程占有的进程
  • 充分条件
  • 循环等待:存在一个闭合的进程链,每个进程至少占有此链中下一个进程所需的一个资源

2.19.3 死锁的解决

  • 死锁预防:防止死锁的四个条件之一
  • 死锁避免:防止循环等待的出现
  • 死锁检测与解除

2.20 死锁预防

  • 间接方法:防止死锁的三个必要条件之一
  • 防止互斥:不可防止
  • 防止占有且等待:要求进程一次性请求所有需要的资源(效率低、需要估计所需要的资源)
  • 防止不可抢占:一个占有资源的进程请求资源不得则释放已占有资源或操作系统要求另一个进程释放资源(需要容易保存资源状态的结构)
  • 直接方法:防止循环等待的出现
  • 防止循环等待:定义一个请求资源的顺序,所有进程对资源的请求必须严格按资源序号递增的顺序提出(低效)

2.21 死锁避免

  • 避免进入不安全状态
  • 与死锁预防相比:允许三个必要条件
  • 动态检查:运行过程中检查进程申请资源的结果是否安全,若会死锁则阻塞,否则予以分配
  • 死锁避免两种方式
  • 资源分配拒绝:若一个进程增加的资源请求导致死锁,则拒绝该请求
  • 进程启动拒绝:若一个进程请求导致死锁,则拒绝启动该进程

2.21.1 银行家算法

属于资源分配拒绝策略,由Dijkstra于1965年提出

思想

用户申请一组资源时,系统判断分配后是否还处于安全状态,若是则允许分配,否则不分配,阻塞用户进程

安全状态

至少有一个资源分配安全序列,按照这个序列分配资源,可以不导致死锁地运行结束,相应的,不存在安全序列就是不安全状态

安全状态的判定
  1. Claim矩阵(后简称C矩阵):各个进程声明想要的资源数量
  2. Allocation矩阵(后简称A矩阵):已经分配给各个进程的资源数量
  3. C-A矩阵:又称Request矩阵:各个进程还需要资源的数量
  4. Resource向量(后简称R向量):各种资源的初始总量
  5. Available向量(后简称A向量):各种资源剩余可用的量

方法:

  1. 查看当前A向量能否满足C-A其中一行
  2. 满足则将A矩阵对应行加到A向量上,继续3,否则不安全
  3. 重复1
  4. C-A为0则得到安全序列

图解:


得到安全序列为P2,P1,P3,P4
  • 安全序列不唯一,A向量满足C-A多行时可以尝试多个序列
  • 安全状态也不一定不会死锁,安全状态时不按照安全序列分配就会死锁
  • 并非所有不安全状态都是死锁状态
//全局数据结构
struct state {int resource [ m ] ;int available [ m ];int claim [ n ][m ] ;int alloc [ n ][m ] ;
}//资源分配算法主体
if (alloc [ i,* ] + request [*]> claim [ i,* 〕)<error >;                  /*total request > claim* /
else if (request [ * ] > available [ * ])<suspend process >;
else {                      /*simulate alloc */<define newstate by :alloc [ i,* ]= alloc [ i,* ]+request [ * ];available [*] = available [ * ] - request [* ] >;
}
if (safe ( newstate ) )< carry out allocation >;
else {<restore original state >;<suspend process >;
}//银行家算法测试安全性
boolean safe (state s) {int currentavail[m];process rest [<number of processes>];currentavail = available;rest = {all processes};possible = true;while (possible) {<find a process Pk in rest such thatclaim [k,* ] - alloc [k,* ] <= currentavail;>if (found) {     /*simulate execution of Pk */currentavail = currentavail + alloc [ k,*];rest = rest - {Pk};}else possible = false;}return ( rest ==null );
}

2.21.2 评价死锁避免

  • 优点
  • 无需死锁预防中的抢占和回滚
  • 比死锁预防限制更少
  • 缺点
  • 必须先得到每个进程声明请求的资源,即要有Claim矩阵
  • 进程执行顺序必须没有要求,否则不能按照安全序列来
  • 分配的资源数量必须固定
  • 占有资源的进程不能退出

2.22 死锁检测与解除

2.22.1 算法步骤

  1. 标记A矩阵中一全零行
  2. 初始化W向量=A向量
  3. 在C-A矩阵查找下标i的进程行,未被标记且这一行<=W向量,若找不到则终止算法
  4. 若找到这样的行,标记进程i,把A矩阵中的相应行加到W向量中,返回3
  5. 当且仅当3终止时,仍有未标记的进程,才存在死锁,未标记的进程都是死锁状态

2.22.1 资源分配图检测方法

资源分配图的化简
  1. 找出全部请求都满足的节点Pi,消去其所有请求边和分配边,使之成为孤立节点
  2. 重复1直至无法化简
示例

可完全简化的,则不存在死锁
不能完全简化时,存在死锁(如下图)

2.22.2 死锁解除

  1. 撤销死锁进程,直到不再存在死锁
  2. 回退,回退到前面定义的某些检查点,重新启动所有进程
  3. 抢占,连续抢占直到不再有死锁

那么撤销哪些进程?又该抢占哪些进程的资源?
选择原则:输出少、剩余时间长、优先级低、目前为止消耗cpu时间少的

2.22.3 三种策略的比较

2.23 哲学家就餐问题

1965年由Dijkstra提出

问题描述

  • 5个哲学家围坐圆桌
  • 5只餐叉间隔摆放
  • 哲学家行为为思考或进餐
  • 哲学家进餐必须同时使用两边的餐叉
  • 思考时蒋餐叉放回原处
  • 两个哲学家不使用同一把叉子
  • 尽量避免死锁和饥饿

如图


方案一 取左叉

都去拿左边的叉子,死锁

semaphore fork[5] = {1, 1, 1, 1, 1};void main()
{cobegin {philosopher(0); philosopher(1); philosopher(2);philosopher(3);    philosopher(4);}coend;
}void philosopher(int i)
{while(true) {think;                      //思考wait(fork[i]);           //拿起左边的叉子wait(fork[(i+1)%5]);     //拿起右边的叉子eat();signal(fork[i]);         //放回左边的叉子signal(fork[(i+1)%5]);   //放回右边的叉子}
}

方案二

请求同时拿两个叉子,被占则等待随机事件再请求,可能活锁

semaphore fork[5] = {1, 1, 1, 1, 1};void main()
{cobegin {philosopher(0); philosopher(1); philosopher(2);philosopher(3);    philosopher(4);}coend;
}void philosopher(int i)
{while(true) {think;              //思考wait(fork[i]);          //拿起左边的叉子timeout(wait(fork[(i+1)%5], [0, T]) //若右边的叉子被占用,则放下左边叉,等待一段随机时间后再拿                           eat();                                                               signal(fork[i]);        //放回左边的叉子signal(fork[(i+1)%5]);  //放回右边的叉子}
}

方案三 资源分级

为资源(这里是餐叉)分配一个偏序(partial order)或者分级(hierarchy)的关系,并约定所有资源都按照这种顺序获取,按相反顺序释放,而且保证不会有两个无关资源同时被同一项工作所需要

① 为餐叉编号
  • 就餐前,先取用编号较低的餐叉,再取用编号较高的餐叉
  • 就餐毕,先放下编号较高的餐叉,再放下编号较低的餐叉
semaphore fork[5] = {1, 1, 1, 1, 1};
void main()
{cobegin {philosopher(0); philosopher(1); philosopher(2);philosopher(3);    philosopher(4);}coend;
}
void philosopher(int i)
{while(true) {think();  //思考if (i  !=  4) {wait(fork[i]); wait(fork[(i+1)%5]);} //先左后右else {wait(fork[(i+1)%5]); wait(fork[i]);} //先右后左eat(); if (i  !=  4) {signal(fork[(i+1)%5]); signal(fork[i]);} //先右后左else {signal(fork[i]); signal(fork[(i+1)%5]);} //先左后右}
}
② 为哲学家编号
  • 奇数号的哲学家必须首先拿左边的餐叉
  • 偶数号的哲学家必须首先拿右边的餐叉
semaphore fork[5] = {1, 1, 1, 1, 1};
void main()
{cobegin {philosopher(0); philosopher(1); philosopher(2);philosopher(3);    philosopher(4);}coend;
}void philosopher(int i)
{while(true) {think();  //思考if (i % 2 != 0) {wait(fork[i]); wait(fork[(i+1)%5]);} //先左后右else {wait(fork[(i+1)%5]); wait(fork[i]);}eat(); signal(fork[(i+1)%5]);                   //先右后左signal(fork[i]);   }
}

方案四 服务生方法

  • 引入一个餐厅服务生,哲学家必须经过他的允许才能拿起餐叉
  • 最多允许4个哲学家同时进食
semaphore fork[5] = {1, 1, 1, 1, 1}, room = 4;
void main()
{cobegin {philosopher(0); philosopher(1); philosopher(2);philosopher(3);    philosopher(4);}coend;
}void philosopher(int i)
{while(true) {think;                          //思考wait(room);                     //占据就餐位置wait(fork[i]);                  //拿起左边的叉子wait(fork[(i+1)%5]);            //拿起右边的叉子signal(fork[i]);                //放回左边的叉子signal(fork[(i+1)%5]);          //放回右边的叉子signal(room);                   //释放就餐位置}
}

引申:And型信号量集

  • 在一个原语中申请需要的多个临界资源,要么全部分,要么一个都不分配
  • AND型信号量集P原语为Swait(Simultaneous Wait),V原语为Ssignal(Simultaneous Signal)。
  • Swait(S1, S2, …, Sn)
  • Ssignal(S1, S2, …, Sn)

管程方案

monitor dining controller;
cond ForkReady [5];                 /*condition variable for synchronization */
boolean fork[ 5]={ true } ;        /*availability status of each fork*/void get_forks (int pid)            /*pid is the philosopher id number */
{int left = pid;int right =(++pid)%5;/*grant the left fork*/if( ! fork [ left])cwait(ForkReady [ left] ); /*queue on condition variable */fork [ left]= false ;/*grant the right fork*/if( ! fork [ right] )cwait(ForkReady [right] );/*queue on condition variable */fork [ right] = false;
}void release_forks ( int pid){int left = pid;int right =(++pid)%5;/*release the left fork*/if( empty (ForkReady [ leftl)   /*no one is waiting for this fork */fork [ left] = true;else                           /*awaken a process waiting on this fork */csignal (ForkReady [ left]);/*release the right fork*/if (empty (ForkReady [right])   /*no one is waiting for this fork*/fork [ right]= true;else                            /*awaken a process waiting on this fork*/csignal (ForkReady [right] );
}void philosopher [ k=0 to 4]      /*the five philosopher clients */
{while (true){<think>;get_forks (k);              /*client requests two forks via monitor * /<eat spaghetti>;release_forks (k);         /*client releases forks via the monitor */}
}

死锁 操作系统第二章知识点归纳总结相关推荐

  1. 进程的描述与控制 操作系统第二章知识点归纳总结

    系列文章 第一章 操作系统概述 第二章 进程调度 第二章 进程的描述与控制 2.1 什么是进程 程序代码+相关数据+程序控制块PCB 当处理器开始执行一个程序的代码时,称这个执行的实体为进程 2.1. ...

  2. 进程调度 操作系统第二章知识点归纳总结

    系列文章 第一章 操作系统概述 第二章 进程的描述与控制 第二章 进程管理 -调度 2.7 调度的类型 长程调度:决定哪个程序能进入系统成为进程,是创建进程的部分,用时最长 中程调度:决定哪个进程能进 ...

  3. 操作系统概述 操作系统第一章知识点归纳总结

    系列文章 第二章 进程的描述与控制 第二章 进程调度 第一章 概述 1.1 目标与功能 1.1.1 操作系统: 控制应用程序的程序 应用程序和硬件间的接口 三大目标: 方便:用户使用 有效:使用系统资 ...

  4. 模拟进程创建、终止、阻塞、唤醒原语_操作系统第二章--进程的描述与控制

    操作系统第二章--进程的描述与控制 前趋图和程序执行 前趋图 前趋图是一个有向无循环图DAG,用来描述进程之间执行的前后关系 初始结点:没有前趋的结点 终止结点:没有后继的结点 重量:表示该结点所含有 ...

  5. 笔记篇:操作系统第二章 进程管理

    笔记篇:操作系统第二章 进程管理 目录 笔记篇:操作系统第二章 进程管理 2.1 进程的基本概念 2.1.1 程序的顺序执行及其特征 2.1.2 前驱图 2.1.3 程序的并发执行及其特征 2.1.4 ...

  6. java第二章复习_JAVA第二章知识点

    JAVA第二章知识点 本章知识梳理 2.1 关键字 2.2 标识符 2.3 变 量 2.4运算符 2.5 程序流程控制 2.6 方法 2.1 关键字 关键字(keyword)的定义和特点 定义:被ja ...

  7. java第二章_JAVA第二章知识点

    JAVA第二章知识点 本章知识梳理 2.1 关键字 2.2 标识符 2.3 变 量 2.4运算符 2.5 程序流程控制 2.6 方法 2.1 关键字 关键字(keyword)的定义和特点 定义:被ja ...

  8. (王道408考研操作系统)第二章进程管理-第三节10:经典同步问题之哲学家进餐问题

    本文接: (王道408考研操作系统)第二章进程管理-第三节6:经典同步问题之生产者与消费者问题 ((王道408考研操作系统)第二章进程管理-第三节7:经典同步问题之多生产者与多消费者问题 (王道408 ...

  9. (王道408考研操作系统)第二章进程管理-第三节8:经典同步问题之吸烟者问题

    本文接: (王道408考研操作系统)第二章进程管理-第三节6:经典同步问题之生产者与消费者问题 ((王道408考研操作系统)第二章进程管理-第三节7:经典同步问题之多生产者与多消费者问题 文章目录 一 ...

最新文章

  1. python wait_window_pywinauto客户端自动化---窗口等待方法
  2. 【必点】程序员自助SDCC热门主题+图书豪华套餐
  3. Spring Cloud之网关搭建
  4. 图形算法 - 模糊函数比较,Blur Function Compare
  5. java biginterger_Java BigInteger类知识点总结
  6. linux下git分支管理,git远程分支管理
  7. 需要在函数中传递的变量
  8. java juc包多线程编程案例:Executor入门示例
  9. POJ - 3613 Cow Relays(Floyd思想+矩阵快速幂+动态规划)
  10. 聚类(part4)--多源数据聚类算法
  11. ❤️作为测试行业的过来人,宝贵的经验分享给刚入行的你
  12. VS2017 远程调试linux(centos).net core
  13. k8s中资源对象单数、复数、简写的区别
  14. 智慧城市——智慧社区解决方案
  15. 卅三先生的工程电磁场讲座.EEm05——边界条件001
  16. String的intern()详解
  17. linux中 halt shutdown
  18. 2020年主流服务器主板,电脑主板怎么选(2020电脑主板选购指南及检测)
  19. 软件测试的测试内容有那些
  20. 国际结算模拟试题及答案

热门文章

  1. GYM 101875 2018 USP-ICMC
  2. 2018-2019-1 20165227 20165228 20165237 实验五 通讯协议设计
  3. centos7下的elasticsearch-6.2.4安装
  4. mysql排序自段为字符串类型问题解决
  5. 去除input填充颜色
  6. hibench测试出现问题--zookeeper
  7. 算法设计与分析 上机题Mergesort
  8. 黑马程序员_Java高新技术--代理
  9. hibernate---id生成策略
  10. 修改Tomcat欢迎界面为自己项目界面