死锁产生的原因以及避免死锁的算法

一.死锁的概念

在多道程序系统中,虽可借助于多个进程的并发执行,来改善系统的资源利用率,提高系统的吞吐量,但可能发生一种危险━━死锁。所谓死锁(Deadlock),是指多个进程在运行中因争夺资源而造成的一种僵局(Deadly_Embrace),当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。一组进程中,每个进程都无限等待被该组进程中另一进程所占有的资源,因而永远无法得到的资源,这种现象称为进程死锁,这一组进程就称为死锁进程。

二.死锁产生的原因

  • 产生死锁的原因主要是:
    (1) 因为系统资源不足。
    (2) 进程运行推进的顺序不合适。
    (3) 资源分配不当等。
    如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

  • 产生死锁的四个必要条件:
    (1) 互斥条件:一个资源每次只能被一个进程使用。
    (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
    (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。


这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。


  • 死锁的解除与预防:
    理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。

二.数据结构设计

(一)可利用资源向量矩阵AVAILABLE。这是一个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态地改变。如果AVAILABLE [j]= K,则表示系统中现有R类资源K个
(二)最大需求矩阵MAX。这是一个n*m的矩阵,用以表示每一个进程对m类资源的最大需求。如果MAX =K,则表示进程i需要R类资源的数目为K。
(三)分配矩阵ALLOCATION。这也是一个n*m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果ALLOCATION =K,则表示进程i当前已分得R类资源的数目为K。 (四)需求矩阵NEED。这也是一个n*m的矩阵,用以表示每一个进程尚需的各类资源数。如果NEED =K,则表示进程i还需要R类资源K个,才能完成其任务。 上述矩阵存在下述关系: NEED = MAX-ALLOCATION

三.算法实现

(一) 初始化 由用户输入数据,分别对可利用资源向量矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。
(二)银行家算法 在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。 银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。 设进程cusneed提出请求REQUEST ,则银行家算法按如下规则进行判断。
(1)如果REQUEST [cusneed] <= NEED[cusneed],则转(2);否则,出错。
(2)如果REQUEST [cusneed] <= AVAILABLE[cusneed],则转(3);否则,出错。 (3)系统试探分配资源,修改相关数据:
AVAILABLE-=REQUEST[cusneed]; ALLOCATION[cusneed]+=REQUEST[cusneed];
NEED[cusneed]-=REQUEST[cusneed];
(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。
(三)安全性检查算法
(1)设置两个工作向量Work=AVAILABLE;FINISH
(2)从进程集合中找到一个满足下述条件的进程,
FINISH==false;
NEED<=Work;
如找到,执行(3);否则,执行(4)
(3)设进程获得资源,可顺利执行,直至完成,从而释放资源。 Work+=ALLOCATION; Finish=true; GOTO 2
(4)如所有的进程Finish= true,则表示安全;否则系统不安全。

四.源程序清单

#include  using namespace std; 
#define MAXPROCESS 50                         /*最大进程数*/
#define MAXRESOURCE 100                         /*最大资源数*/  
int AVAILABLE[MAXRESOURCE];                     /*可用资源数组*/  
int MAX[MAXPROCESS][MAXRESOURCE];             /*最大需求矩阵*/ 
int ALLOCATION[MAXPROCESS][MAXRESOURCE];     /*分配矩阵*/ 
int NEED[MAXPROCESS][MAXRESOURCE];             /*需求矩阵*/  
int REQUEST[MAXPROCESS][MAXRESOURCE];         /*进程需要资源数*/ 
bool FINISH[MAXPROCESS];                         /*系统是否有足够的资源分配*/ 
int p[MAXPROCESS];                             /*记录序列*/
int m,n;                                     /*m个进程,n个资源*/ void Init(); bool Safe(); void Bank(); int main() 
{       
    Init();      
    Safe();      
    Bank(); 
}  
void Init()                 /*初始化算法*/
{       
    int i,j;           
    cout<<"请输入进程的数目:";      
    cin>>m;       
    cout<<"请输入资源的种类:";      
    cin>>n;       
    cout<<"请输入每个进程最多所需的各资源数,按照"<"x"<"矩阵输入"<for(i=0;ifor(j=0;jcin>>MAX[j];       
    cout<<"请输入每个进程已分配的各资源数,也按照"<"x"<"矩阵输入"<for(i=0;ifor(j=0;jcin>>ALLOCATION[j];
            NEED[j]=MAX[j]-ALLOCATION[j];
            if(NEED[j]<0)              
            {                   
                cout<<"您输入的第"<1<<"个进程所拥有的第"<1<<"个资源数错误,请重新输入:"<continue;
            }          
        }      
    }       
    cout<<"请输入各个资源现有的数目:"<for(i=0;icin>>AVAILABLE;
    } 
}  
void Bank()                 /*银行家算法*/ 
{
    int i,cusneed;
    char again;
    while(1)
    {
        cout<<"请输入要申请资源的进程号(注:第1个进程号为0,依次类推)"<cin>>cusneed;
        cout<<"请输入进程所请求的各资源的数量"<for(i=0;icin>>REQUEST[cusneed];
        }
        for(i=0;iif(REQUEST[cusneed]>NEED[cusneed])
            {
                cout<<"您输入的请求数超过进程的需求量!请重新输入!"<continue;
            }
            if(REQUEST[cusneed]>AVAILABLE)
            {
                cout<<"您输入的请求数超过系统有的资源数!请重新输入!"<continue;
            }
        }
        for(i=0;iif(Safe())
        {
            cout<<"同意分配请求!"<else
        {
            cout<<"您的请求被拒绝!"<for(i=0;ifor(i=0;ifalse;
        }
        cout<<"您还想再次请求分配吗?是请按y/Y,否请按其它键"<cin>>again;
        if(again=='y'||again=='Y')
        {
            continue;
        }
        break;
    }
}
bool Safe()/*安全性算法*/ 
{
    int i,j,k,l=0;
    int Work[MAXRESOURCE];/*工作数组*/
    for(i=0;ifor(i=0;ifalse;
    }
    for(i=0;iif(FINISH==true)
        {
            continue;
        }
        else
        {
            for(j=0;jif(NEED[j]>Work[j])
                {
                    break;
                }
            }
            if(j==n)
            {
                FINISH=true;
                for(k=0;k1;
            }
            else
            {
                continue;
            }
        }
        if(l==m)
        {
            cout<<"系统是安全的"<cout<<"安全序列:"<for(i=0;icout<if(i!=l-1)
                {
                    cout<<"-->";
                }
            }
            cout<<""<return true;
        }
    }
    cout<<"系统是不安全的"<return false;
}

五.实验分析:

(1)下列状态是否安全?(三个进程共享12个同类资源) 进程 已分配资源数 最大需求数
1 1 4 (状态a)
2 4 4
3 5 8
1 1 4 (状态b)
2 4 6
3 6 8
状态a安全,序列为:2–>1–> 3
状态b不安全,只剩1个可用资源,收不回已分配资源。
(2)考虑下列系统状态

分配矩阵 最大需求矩阵 可用资源矩阵
0 0 1 2 0 0 1 2 1 5 2 0
1 0 0 0 1 7 5 0
1 3 5 4 2 3 5 6
0 6 3 2 0 6 5 2
0 0 1 4 0 6 5 6

问系统是否安全?若安全就给出所有的安全序列。若进程2请求(0420),可否立即分配?
答:安全。安全序列为:1–>3–>2–>5–>4。 若进程2请求(0420),可立即分配。分配后可用资源为1 1 0 0,回收1进程资源, 可用资源数为:1 1 1 2,然后执行3–>2–>5–>4序列。

你可能感兴趣的:(简单C编程)