死锁的定义 和 处理策略

目录

一、死锁的定义:

二、发生资源死锁的四个必要条件:

三、死锁的模型

四、四种处理死锁的策略:

五、经典的IPC问题     哲学家就餐问题


一、死锁的定义:

如果一个进程集合中的  每个进程  都在等待 只能由进程集合中的其他进程 才能引发的事件,那么,该进程集合就是死锁的。

进程的数量以及占有或者请求的资源数量和种类都是无关紧要的,而且无论资源是何种类型(软件或者硬件)都会发生这种结果。这种死锁称为 资源死锁(resource deadlock),这是常见的类型。

由于所有的进程都在等待,所有没有一个进程能引发可以唤醒该进程集合中的其他进程的事件, 这样, 所有的进程都 会无限期的等待下去。

二、发生资源死锁的四个必要条件:

1. 互斥条件

        每个资源要么已经分配给一个进程,要么就是可用的。

2. 占有和等待条件

        已经得到了某个资源的进程,可以再请求新的资源。

3. 不可抢占条件

        已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。

4. 环路等待条件

        死锁发生时,系统中一定有由两个或两个以上的进程组成的一条环路,该环路中的每个进程都在等待着下一个进程所占有的资源。

死锁发生时,以上四个条件一定是同时满足的。 如果其中任何一个条件不成立,死锁就不会发生。

三、死锁的模型

用圆形表示 进程, 用方形表示 资源。     从资源节点到进程节点的有向边代表该资源已被请求、授权并被进程占用。   从进程节点到资源节点的有向边代表当前进程正在请求该资源,并且该进程已被阻塞,处于等待该资源的状态。

                                                                                   

 左图含义是: 当前资源R正被进程A占用   ;  右图含义是: 进程B正在等待着资源S

 死锁的模型示例如下:

 上图所示的进程都进入了死锁的状态: 

进程C等待这资源T, 资源T被进程D占用着, 进程D又等待着由进程C占用的资源U。   

 这样两个进程都得等待下去, 也就是两个进程 在争夺 两个资源,最终形成了 ,谁都无法使用资源的状态。

进程对资源的请求,与 资源的占用模型,只要能形成环, 环上的所有进程都是死锁进程。

四、四种处理死锁的策略:

1.忽略该问题。  也许如果你忽略它,它也会忽略你

2.检测死锁并恢复。  让死锁发生,检测他们是否发生,一旦发生死锁,采取行动解决问题。

3.仔细对资源进行分配,动态地避免死锁。

4.通过破坏死锁的四个必要条件之一,防止死锁的产生。

五、经典的IPC问题     哲学家就餐问题

问题描述:

哲学家的生活中有两种交替活动时段:即吃饭和思考。   当一个哲学家觉得饿了时,他就试图分两次去取其左边和右边的叉子,就开始吃饭,吃完后放下叉子继续思考。

能为下图中五个哲学家,每一个哲学家写一段描述其行为的程序,且决不会死锁吗?

 现在操作系统 ,提供的一种可行的解决方案:

#define N       5              /*哲学家数目*/
#define LEFT    (i+N-1)%N      /*i的左邻居编号*/
#define RIGHT   (i+1)%N        /*i的右邻居编号*/
#define THINKING 0             /*哲学家在思考*/
#define HUNGRY   1             /*哲学家试图拿起叉子*/
#define EATING   2             /*哲学家进餐*/
typedef int  semaphore;        /*信号量 是一种特殊的整型数据*/
int  state[N];                 /*数组用来跟踪记录每位哲学家的状态*/
semaphore mutex = 1;           /*临界区的互斥*/
semaphore s[N];                /*每个哲学家一个信号量*/

void philosopher(int i)        /*i:哲学家编号,从0 到 N-1*/
{
    while(true)                /*无限循环*/
    {
    }
}  

void take_forks(int i)         /*i:哲学家编号,从 0到 N-1*/
{
    down(&mutex);              /*进入临界区*/
    state[i] = HUNGRY;         /*记录哲学家i处于饥饿的状态*/
    test(i);                   /*尝试获取2把叉子*/
    up(&mutex);                /*离开临界区*/
    down(&s[i]);               /*如果得不到需要的叉子则阻塞*/
}

void put_forks(i)              /*i:哲学家编号,从0到N-1*/
{
    down(&mutex);              /*进入临界区*/
    state[i] = THINKING;       /*哲学家已经就餐完毕*/
    test(LEFT);                /*检查左边的邻居现在可以吃吗*/
    test(RIGHT);               /*检查右边的邻居现在可以吃吗*/
    up(&mutex);                /*离开临界区*/
}

void test(i)                   /*i:哲学家编号,从0到N-1*/
{
    if(state[i] == HUNGRY && state[LEFT]!=EATING && state[RIGHT]!=EATING)
    {
        state[i] = EATING;
        up(&s[i]);
    }
}

算法中使用一个数组state跟踪每一个哲学家是在进餐、思考还是饥饿状态,  一个哲学家只有在两个邻居都没有进餐时,才允许进入到进餐状态。  

程序使用了一个信号量数组, 每个信号量对应一位哲学家,这样在所需的叉子被占用时,想进餐的哲学家就被阻塞。

注意,每个进程将过程philosopher作为主代码运行,而其他过程take_forks、put_forks 和 test 只是普通的过程,而非单独的进程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值