死锁 —— 银行家算法

死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象:死锁。

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件
1)互斥条件:进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
*********************************************************************************************************************************************************************************** 银行家算法:避免思索的发生。

算法思想:

       1、假分配检测:Request < Need

                            Request < Available

       2、安全序列检测算法

实例列举:

  某系统有R1,R2,R3共3中资源,在T0时刻P0,P1,P2,P3和P4这5个进程对资源的占用和需求情况如下表1,此时系统的可用资源向量为(3,3,2)。试问:

1、T0时刻系统是否存在安全序列?

2、P1请求资源:P1发出请求向量Request(1,0,2),系统是否接受该请求?请使用银行家算法检查

3、P4请求资源:P4发出请求向量Request(3,3,0),系统按银行家算法检查.

4、P0请求资源:P0发出请求向量Request(0,2,0),系统按银行家算法检查.

      表1 T0时刻的资源分配表

  MAX Allocation Need Available
P0            7 5 3         0 1 0         7 4 3          3 3 2        
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  

 

an:

  1、T0时刻系统是否存在安全序列?

    Available > Need1 —-> 可用资源分配给P1,直到P1进程执行完成,然后Available = Available + Allocation1 = (5,3,2)

           Available > Need3 —–> 可用资源分配给P3,直到P3进程执行完成,然后Available = Available + Allocation3 = (7,4,3)

    Available> Need4…..

        得到安全序列为:P1,P3,P4,P2,P0

  2、P1请求资源:P1发出请求向量Request(1,0,2),系统是否接受该请求?请使用银行家算法检查

   第一步(假分配检查):把Request分配给P1,必须满足Request要小于Available,Request要小于Need。

                       Request(1,0,2)< Available(3,3,2)

                       Request(1,0,2)< Need(1,2,2)

        因为满足第一步检查,进入第二层检查(安全序列检查)。

   第二步(安全序列检查):建立安全性检查表

  Work Need Allocation Work+Allocation Finish
P1 2 3 0 0 2 0 3 0 2    
           
           
           
           

  如果 Work > Need ,那么执行Work+Allocation,得到:                

  Work Need Allocation Work+Allocation Finish
P1   2 3 0 0 2 0     3 0 2  5 3 2  true
  5 3 2            
           
           
           

   找到Need<Work的进程,如果没有找到这样的进程而进程集合没有执行,则算法返回,得到不存在安全序列结果,否则继续执行该算法。

   这里我们找到了P3进程。修改安全序列检查表:

  Work Need Allocation Work+Allocation Finish
P1   2 3 0 0 2 0     3 0 2  5 3 2  true
P3 5 3 2     0 1 1 2 1 1  7 4 3  true
  7 4 3        
           
           

  这样一直执行到所有的进程到完成,以完成该安全序列检查表:

  Work Need Allocation Work+Allocation Finish
P1   2 3 0 0 2 0     3 0 2  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
P0 7 4 5 7 4 3 0 1 0  7 5 5  true
P2 7 5 5 6 0 0 3 0 2 10 5 7  true

      这样就找到了整个安全序列为:P1,P3,P4,P0,P2

    3、4小问也是同样的解题过程。这里不赘述…

****************************************************************************************************

算法流程图:

1.初始化算法流程图:

《死锁 —— 银行家算法》

2.银行家算法流程图:

《死锁 —— 银行家算法》

 3.安全性算法流程图:

《死锁 —— 银行家算法》
算法设计:
1.设进程i提出请求Request[n],则银行家算法按如下规则进行判断。

(1)如果Request[n]>Need[i,n],则报错返回。

(2)如果Request[n]>Available,则进程i进入等待资源状态,返回。

(3)假设进程i的申请已获批准,于是修改系统状态:

    Available=Available-Request

    Allocation=Allocation+Request

    Need=Need-Request

(4)系统执行安全性检查,如安全,则分配成立;否则试探险性分配作废,系统恢复原状,进程等待。

2.安全性检查

(1)设置两个工作向量Work=Available;Finish =False

(2)从进程集合中找到一个满足下述条件的进程,

   Finish =False

   Need<=Work

   如找到,执行(3);否则,执行(4)

(3)设进程获得资源,可顺利执行,直至完成,从而释放资源。

    Work=Work+Allocation

    Finish=True

    GO TO 2

(4)如所有的进程Finish =true,则表示安全;否则系统不安全。
数据结构:
假设有M个进程N类资源,则有如下数据结构:

#define W 10

#define R 20

int A ;                      //总进程数

int B ;                     //资源种类

int ALL_RESOURCE[W];        //各种资源的数目总和

int MAX[W] ;             //M个进程对N类资源最大资源需求量

int AVAILABLE ;          //系统可用资源数

int ALLOCATION[W] ;      //M个进程已经得到N类资源的资源量

int NEED[W] ;            //M个进程还需要N类资源的资源量

int Request ;            //请求资源个数

主要函数说明

void showdata();           //主要用来输出资源分配情况

void changdata(int);       //主要用来输出资源分配后后的情况

void rstordata(int);       //用来恢复资源分配情况,如:银行家算法时,由于分配不安全则要恢复资源分配情况

int chkerr(int);           //银行家分配算法的安全检查

void bank()   ;             //银行家算法

数据结构分析:

假设有M个进程N类资源,则有如下数据结构:

#define W 10

#define R 20

int A ;                      //总进程数

int B ;                     //资源种类

int ALL_RESOURCE[W];        //各种资源的数目总和

int MAX[W] ;             //M个进程对N类资源最大资源需求量

int AVAILABLE ;          //系统可用资源数

int ALLOCATION[W] ;      //M个进程已经得到N类资源的资源量

int NEED[W] ;            //M个进程还需要N类资源的资源量

int Request ;            //请求资源个数

代码如下:

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<<"\t---------------------------------------------------"<<endl;
    cout<<"\t||                                               ||"<<endl;
    cout<<"\t||                 银行家算法                    ||"<<endl;
    cout<<"\t||                                               ||"<<endl;
    cout<<"\t||                             计科04151  李宏   ||"<<endl;
    cout<<"\t||                                               ||"<<endl;
    cout<<"\t||                                  0415084211   ||"<<endl;
    cout<<"\t---------------------------------------------------"<<endl;
    cout<<"请输入进程的数目:";
    cin>>m;
    cout<<"请输入资源的种类:";
    cin>>n;
    cout<<"请输入每个进程最多所需的各资源数,按照"<<m<<"x"<<n<<"矩阵输入"<<endl;
    for(i=0;i<m;i++)
    for(j=0;j<n;j++)
    cin>>MAX[j];
    cout<<"请输入每个进程已分配的各资源数,也按照"<<m<<"x"<<n<<"矩阵输入"<<endl;
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            cin>>ALLOCATION[j];
            NEED[j]=MAX[j]-ALLOCATION[j];
            if(NEED[j]<0)
            {
                cout<<"您输入的第"<<i+1<<"个进程所拥有的第"<<j+1<<"个资源数错误,请重新输入:"<<endl;
                j--;
                continue;
            }
        }
    }
    cout<<"请输入各个资源现有的数目:"<<endl;
    for(i=0;i<n;i++)
    {
        cin>>AVAILABLE;
    }
}
void Bank()                /*银行家算法*/
{
    int i,cusneed;
    char again;
    while(1)
    {
        cout<<"请输入要申请资源的进程号(注:第1个进程号为0,依次类推)"<<endl;
        cin>>cusneed;
        cout<<"请输入进程所请求的各资源的数量"<<endl;
        for(i=0;i<n;i++)
        {
            cin>>REQUEST[cusneed];
        }
        for(i=0;i<n;i++)
        {
            if(REQUEST[cusneed]>NEED[cusneed])
            {
                cout<<"您输入的请求数超过进程的需求量!请重新输入!"<<endl;
                continue;
            }
            if(REQUEST[cusneed]>AVAILABLE)
            {
                cout<<"您输入的请求数超过系统有的资源数!请重新输入!"<<endl;
                continue;
            }
        }
        for(i=0;i<n;i++)
        {
            AVAILABLE-=REQUEST[cusneed];
            ALLOCATION[cusneed]+=REQUEST[cusneed];
            NEED[cusneed]-=REQUEST[cusneed];
        }
        if(Safe())
        {
            cout<<"同意分配请求!"<<endl;
        }
        else
        {
            cout<<"您的请求被拒绝!"<<endl;
            for(i=0;i<n;i++)
            {
                AVAILABLE+=REQUEST[cusneed];
                ALLOCATION[cusneed]-=REQUEST[cusneed];
                NEED[cusneed]+=REQUEST[cusneed];
            }
        }
        for(i=0;i<m;i++)
        {
            FINISH=false;
        }
        cout<<"您还想再次请求分配吗?是请按y/Y,否请按其它键"<<endl;
        cin>>again;
        if(again=='y'||again=='Y')
        {
            continue;
        }
        break;
        }
}
bool Safe()                                    /*安全性算法*/
{
    int i,j,k,l=0;
    int Work[MAXRESOURCE];                    /*工作数组*/
    for(i=0;i<n;i++)
    Work=AVAILABLE;
    for(i=0;i<m;i++)
    {
        FINISH=false;
    }
    for(i=0;i<m;i++)
    {    
        if(FINISH==true)
        {
            continue;
        }
        else
        {
            for(j=0;j<n;j++)
            {
                if(NEED[j]>Work[j])
                {
                    break;
                }
            }
            if(j==n)
            { 
                FINISH=true;
                for(k=0;k<n;k++)
                {
                    Work[k]+=ALLOCATION[k];
                }
                p[l++]=i;
                i=-1;
            }
            else
            {
                continue; 
            }
        }
        if(l==m)
        {
            cout<<"系统是安全的"<<endl;
            cout<<"安全序列:"<<endl;
            for(i=0;i<l;i++)
            {
                cout<<p;
                if(i!=l-1)
                {
                    cout<<"-->";
                }
            }
            cout<<""<<endl;
            return true;
        }
    }
    cout<<"系统是不安全的"<<endl;
    return false;
} 

结果:
《死锁 —— 银行家算法》

    原文作者:银行家问题
    原文地址: https://blog.csdn.net/w825828482/article/details/20444207
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞