OS chapter 2 Deadlock and starvation

产生死锁与互斥的原因;

解决死锁;

死锁与同步的经典问题:哲学家进餐问题

 

 原因:因为进程间的竞争资源或通信不当,造成进程的永久信阻塞;

没有有效的解决方法;

可能会有单进程的死锁;

 1 /* P */
 2 get A;
 3 ...
 4 get B;
 5 ...
 6 release A;
 7 ...
 8 release B;
 9 
10 /* Q */
11 get B;
12 ...
13 get A;
14 ...
15 release B;
16 ...
17 release A;
// 可能会出现死锁

可重用资源:处理器、I/O通道、主存、辅存等

进程占有一个资源请求其它资源就可能会出现死锁;

可消耗资源:中断、消息等

如两个进程都是采用阻塞接收消息,且两个进程分别要接收对方的消息,则可能出现阻塞;

 

产生死锁的原因

  • 互斥使用
  • 占有并等待
  • 不剥夺
  • 环路等待

 

死锁的预防

以四个条件为考虑,分析是一个问题,但工程来说是不可用,降低了系统的性能;

间接方法

  • 互斥:不能禁止;
  • 保持与等待:要求进程一次性申请其所需资源,若系统中没有足够的资源可能造成进程阻塞,使得系统效率低;
  • 不剥夺:高优先权剥夺低优先权进程对资源的使用权;
  • 环路等待:

直接方法

  • 禁止环路等待:对系统资源类型进行排队,进程对某类资源的申请只能按序号递增的方式进行;

 

避免死锁 Deadlock Avoidance

在为进程分配资源之前,首先通过计算判断此次分配是否分导致死锁,只有不导致死锁的分配才是可行的。

 

银行家算法

安全状态:系统为某个进程序列分配其所需的资源直到最大需求,使得每个进程都可以顺序完成则系统称为安全状态;

通过需求矩阵、已分配矩阵、可用资源矩阵、还要的资源矩阵,即可知道按什么顺序执行进程不会进入不安全状态;

为了实现银行家算法,系统中必须实现某些数据结构;

数据结构

  • 资源可以向量
  • 最大需求矩阵n*m
  • 分配矩阵n*m
  • 还需矩阵n*m 

特点:

  • 必须预先知道每个进程需要的资源总量
  • 每次都要算,对系统性能损耗大
  • 进程必须释放资源,这个不一定

 

检测死锁 Deadlock Detection

周期性的执行死锁检测,看系统中是否有环路等待;

 

哲学家进餐问题

要求:使所有哲学家都能进餐,且不会有人出现饥饿;

 1 /* 会造成死锁的算法 */
 2 semaphore fork[5] = {1,1,1,1,1};  /* 筷子信号量初始化为1 */
 3 int i;
 4 while(1)
 5 {
 6     think;
 7     wait(fork[i]); /*拿起左边的筷子 */
 8     wait(fork[(i+1)%5]); /*拿起右边的筷子 */
 9     eat;
10     signal(fork[(i+1)%5]);
11     signal(fork[i]);
12 }

 

上面这个算法会造成死锁,因为如果5个哲学家都运行到7的时候被中断,则会死锁;

原因是系统中同时运行的进程太多了,系统处于高竞争状态;所以可以考虑减少同时运行的进程数,即挂起一定数量的进程;

 1 /* 改进的算法 */
 2 semaphore fork[5] = {1,1,1,1,1};  /* 筷子信号量初始化为1 */
 3 int i;
 4 semaphore room = 4; /* 信号量初始化为4,最多允许4个哲学家同时进来 */
 5 while(1)
 6 {
 7     think;
 8     wait(room); /* 当room<=0则挂起 */
 9     wait(fork[i]); /*拿起左边的筷子 */
10     wait(fork[(i+1)%5]); /*拿起右边的筷子 */
11     eat;
12     signal(fork[(i+1)%5]);
13     signal(fork[i]);
14     signal(room); /* 唤醒队列中的哲学家 */
15 }

 

posted on 2014-11-17 18:02  He2Li  阅读(86)  评论(0)    收藏  举报