C#窗体模拟银行家算法

Posted nepu_hua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#窗体模拟银行家算法相关的知识,希望对你有一定的参考价值。

源码下载

模拟内容

银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。

设计一个N(如N=5)个并发进程共享M(如M=3)种类不同资源的系统,给定各类资源的初始数目,进程可动态地申请资源和释放资源,系统按各进程的申请动态地分配资源。

设计银行家算法,实现资源分配程序,应能打印输出各进程依次要求申请的资源数和依次分配资源情况、每次申请是否为安全状态、安全状态下安全序列的情况等。

运行时,模拟出各种情况,输出各个数据结构的具体数值。

模拟思路

1、设计数据结构
为实现银行家算法,系统必须设置若干数据结构:如Available、Max、Allocation、Need、Work、Finish。这些数据结构记录了相关的信息。

2、分析银行家算法步骤
设进程Pi(i=1,…,N)提出请求Requesti,则银行家算法按如下规则进行判断。
(1)如果Requesti<=NEEDi,则转(2);否则,提示出错。
(2)如果Requesti<=Available,则转(3);否则,提示出错。
(3)系统试探分配资源,修改相关数据:

 	Available = Available -Requesti
	Allocationi = Allocationi +Requesti
	Needi = Needi -Requesti

(4)系统执行安全性检查(调用安全性算法),如是安全状态,则分配成立;否则试探性分配作废,系统恢复原状,进程Pi的此次请求不予满足。

3、安全性算法
(1)初始时,Work:=Available;Finish[i]=false;
(2)从进程集合中找到一个能满足下述条件的进程;

	 ①Finish[i]=false;
	 ②Needi≤Work;若找到,执行步骤(2),否则,执行步骤(3)

(3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

	Work:=Work+Allocationi;
	Finish[i]:=true;
	go to step (2)

(4)如果所有进程的Finish[i]=true都满足,则表示系统处于安全状态,输出安全序列;否则,系统处于不安全状态。

实现方法

使用数组存放Available、Max、Allocation、Need、Work、Finish等信息。采用线程的sleep函数让线程在指定位置挂起一定的时间减缓数据变化的速度来一行一行的动态演示每个进程申请资源、释放资源的过程。

编程实现

初始化一些全局变量如Available、Max、Allocation、Need、Work、Finish等。

	static int[] available = new int[3] { 3, 3, 2 };         //资源数  
    static int[,] max = new int[5, 3]{{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};          //最大资源需求
    static int[,] allocation = new int[5, 3]{{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}};   //已经分配的资源
    static int[,] need = new int[5, 3]{{7,4,3},{1,2,2},{6,0,0},{0,1,1},{4,3,1}};         //还需要的资源
    static int[] request = new int[3];         //存放请求
    bool[] finish = new bool[5] { false,false,false,false,false};
    int[] work = new int[3];
    int[] queue = new int[5];   //由于存放安全队列  
    int thread;  //线程号  

编写函数对用户输入要申请资源的进程和申请的资源数进行判断。如果进程申请的资源数超出其所需要的资源数则在对应的label控件上显示进程申请的资源超出其需要的资源,请重新输入" 。如果进程申请的资源数大于当前系统可用资源,在label控件上提示 进程申请的资源大于系统可用资源,请重新输入。

public void getThread()
{
    for (int i = 0; i < 5; i++)
    {
        finish[i] = false;
        updatefinish(i);
    }
    //获取请求资源的进程号
    int thread = this.cmb1.SelectedIndex;
    this.thread = thread;
    //初始化request数组
    request[0] = int.Parse(this.tb1.Text);
    request[1] = int.Parse(this.tb2.Text);
    request[2] = int.Parse(this.tb3.Text);
    if (request[0] > need[thread, 0] || request[1] > need[thread, 1] || request[2] > need[thread, 2])
    {
        this.lbnote.Text ="p"+ thread + "进程申请的资源超出其需要的资源,请重新输入";
    }
    else if (request[0] > available[0] || request[1] > available[1] || request[2] > available[2])
    {
        this.lbnote.Text ="p"+ thread + "进程申请的资源大于系统可用资源,请重新输入";
    }
    else {
         this.lbnote.Text = "试分配资源中。。。";
         Thread.Sleep(3000);
         changeData(thread);
         init();
         this.lbnote.Text = "分配成功!";
         Thread.Sleep(3000);
        this.lbnote.Text = "安全性检查中。。。";
         if (!check(thread)) { 
              recoverData(thread);
         }
    }
 }

进程请求的资源数符合要求,进行试探性分配资源,改变对应变量的值。

public void changeData(int thread)
{
    for (int i = 0; i < 3; i++)
    {
        //重新调整系统资源数  
        available[i] -= request[i];
        //计算各个线程拥有资源  
        allocation[thread, i] += request[i];
        //重新计算需求  
        need[thread, i] -= request[i];
    }
}

安全性算法,对试分配资源后的系统进行安全性检查,如果是安全的生成安全性序列。

public bool check(int thread)
{
    int k = 0;//安全队列下标  
    int j;  //要判断的线程  
    int i;
    //初始化finish向量
    for (i = 0; i < 5; i++) {
        finish[i] = false;
    }
    j = thread;
    //初始化work向量
    for (i = 0; i < 3; i++)
    {
        work[i] = available[i];
    }
    while (j < 5)
    {
        for (i = 0; i < 3; i++)
        {
            if (finish[j])
            {
                j++;
                break;
            }
            else if (need[j, i] > work[i])
            {
                j++;
                break;
            }
            else if (i == 2)
            {
               Thread.Sleep(2000);
               update(j);
               for (int m = 0; m < 3; m++)
               {
                    work[m] += allocation[j, m];  
               }
                finish[j] = true;
                Thread.Sleep(1000);
                updatefinish(j);
                queue[k] = j;
                k++;
                j = 0;   //从最小进程再开始判断  
            }
        }
    }

    //判断是否都属于安全状态  
    for (int p = 0; p < 5; p++)
    {
        if (finish[p] == false)
        {
            this.lbnote.Text = "系统不安全,资源申请失败";
            return false;
        }
    }

    string str="";
    for (int q = 0; q < 5; q++)
    {
        str +='p'+ queue[q].ToString()+"->";
    }
    this.lbnote.Text="p"+thread+"进程资源申请成功,安全序列为:"+str;
    return true;
}

安全性检查不通过,分配失败时调用,恢复系统原状。

public void recoverData(int thread)
{
    for (int i = 0; i < 3; i++)
    {
        //重新调整系统资源数  
        available[i] += request[i];
        //计算各个线程拥有资源  
        allocation[thread, i] -= request[i];
        //重新计算需求  
        need[thread, i] += request[i];
    }
}  

提交按钮点击事件

 private void button1_Click(object sender, EventArgs e)
    {
        Thread thread1 = new Thread(new ThreadStart(getThread));
        thread1.Start();
    }

运行结果

运行之后进入系统首页如图所示。
在这里插入图片描述
选择相应的进程,并输入请求的资源数,点击开始测试,如果请求的资源数大于该进程需要的资源数,系统提示该进程申请的资源超出其需要的资源,请重新输入,如图所示。

在这里插入图片描述
如果输入的进程请求的资源大于系统当前可用的资源,系统提示该进程申请的资源大于系统可用资源,请重新输入,如图所示。
在这里插入图片描述
如果用户输入的数据合理,系统会进行资源试分配,修改该进程的 Allocation和Need的值,同时改变系统的可用资源数并提示分配成功如图所示。
在这里插入图片描述
随后系统进行安全性检查,逐行动态以动态演示每个进程申请资源、释放资源的过程并提示安全性检查中,效果如图所示。
在这里插入图片描述
安全性检查通过,系统将得到的安全序列打印到屏幕上,效果如图所示。
在这里插入图片描述

如果安全性检查失败,无法找到安全序列,系统提示不安全,资源申请失败,效果如图所示。

在这里插入图片描述

以上是关于C#窗体模拟银行家算法的主要内容,如果未能解决你的问题,请参考以下文章

《C#零基础入门之百识百例》(五十八)接口 -- 模拟银行存储

C程序模拟实现银行家算法

c# 做一个DES算法加密解密的窗体

C#模拟银行窗口模拟系统(控制台)

C#窗体中按钮按照一定规则摆放位置的算法

模拟实现银行家调度算法