死锁 —— 银行家算法

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

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件
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;
} 

结果:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
银行家算法是一种经典的避免死锁的算法,它可以确保系统在分配资源时不会进入死锁状态。该算法主要分为两个过程:安全性检查和资源分配。 安全性检查: 在系统运行时,银行家算法需要进行安全性检查,以确定当前状态是否安全。安全状态指的是系统可以满足所有进程的资源需求,而不会陷入死锁状态。 实现该算法需要维护以下数据结构: - Available:表示系统中可用的资源数目。 - Allocation:表示已经分配给各个进程的资源数目。 - Need:表示每个进程还需要的资源数目。 具体实现过程如下: 1. 初始化工作: 首先,需要计算出每个进程的所需资源数目,即 Need 数组。这可以通过计算 Max - Allocation 来得到,其中 Max 表示进程所需的最大资源数目。 2. 安全性检查: 银行家算法的安全性检查基于两个概念:安全序列和安全状态。 安全序列:指的是一系列进程的执行顺序,这些进程都能够完成任务,不会进入死锁状态。 安全状态:指的是系统可以分配资源,使得所有进程都能够完成任务,不会进入死锁状态。 安全性检查的具体实现过程如下: (1)初始化工作: 设置 Work 数组为 Available 数组的值;Finish 数组的值都为 false。 (2)循环检查: 循环检查所有进程,找到一个满足以下条件的进程: - Finish[i] = false - Need[i] <= Work 如果找到了这样的进程,则将该进程的资源释放,并将它加入安全序列中。同时,更新 Work 数组的值。 如果没有找到这样的进程,则说明系统无法满足所有进程的资源需求,进入死锁状态。 3. 资源分配: 如果系统处于安全状态,则可以进行资源分配。资源分配的过程需要按照以下规则进行: - 判断是否能够满足当前进程的资源需求(即 Need[i] <= Available)。 - 如果可以满足,则将资源分配给该进程,同时更新 Available 和 Allocation 数组的值。 - 如果无法满足,则该进程必须等待资源。 需要注意的是,资源分配过程中,需要检查是否会破坏系统的安全状态。如果分配资源后,系统无法保持安全状态,则应该撤销分配操作,等待系统恢复到安全状态后再进行分配。 综上所述,银行家算法是一种非常重要的避免死锁的算法。通过合理地分配系统资源,可以避免系统陷入死锁状态,提高系统的可靠性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值