1. 程式人生 > >[C#]銀行家演算法的實現

[C#]銀行家演算法的實現

1.死鎖

死鎖,顧名思義,是一種鎖住不可自行解開的死局。

在作業系統中,“死鎖”用於描述資源分配時,程序互相搶佔資源,又因為需求的資源被別的程序搶佔,只好互相等待,以至於等待迴圈中的所有程序均無法正常執行的情況。

死鎖形成需要四個條件,這四個條件缺少一個,就不會形成死鎖。

死鎖的四個條件

1)互斥條件

    即對於某資源在一段時間內僅允許一個程序佔有使用。

2)佔有且等待條件/請求和保持條件

    在程序已經佔有一個或多個資源的情況下,若它仍申請新的資源,在等待獲得新的資源時,程序仍會繼續佔有舊有資源,不會主動釋放。

3)不可搶佔條件

    直到佔有該資源的程序使用完畢之前,其他任何程序均不應該強行搶佔該資源。

4)迴圈等待條件

    若干個程序之間形成了一個等待迴圈。

2.安全狀態

若針對目前資源分配情況,系統可以找到某種次序為程序分配資源,使得所有程序能夠依次執行成功,則稱系統此時的分配狀態是安全的,分配資源的次序稱為“安全序列”。

安全狀態時系統中無死鎖,所以所有避免死鎖的演算法都儘可能地使系統進入安全狀態。

值得注意的是,即使是安全狀態下的系統,如果資源分配不當,仍然可以使系統變為不安全狀態。

3.銀行家演算法

1)設計思想

在系統中,程序發起一項資源分配請求,由系統檢查是否可以滿足該分配請求,若可以,應暫時滿足該請求,並檢視此時系統是否仍是安全狀態。

2)程式流程圖

可以分為三個功能模組,第一個模組檢查需求是否可以被滿足,第二個模組檢查系統是否安全,第三個模組是主程式,通過呼叫前兩個模組實現資源分配或請求駁回。

3)資料結構

設有m種資源,n個程序。

int[] Available[m] 系統內可用資源

int[,] Max[n,m] 程序對每種資源的最大需求

int[,] Allocation[n,m] 已分配給各個程序的資源

int[,] Need[n,m] 目前各個程序對各個資源的需求數

[顯然有Need=Max-Allocation]

int[,] Require[m] 對於各種資源的請求函式

bool[] Finish[n] 程序是否可以成功執行的標誌

int[] Work[m] 用於分配資源的向量

[定義:Work=Available-Require]

4)窗體設計

5)窗體程式碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace bank
{
    public partial class Form1 : Form
    {
        public int n = 1;//程序數目
        public int m = 1;//資源分類數
        int[,] Allocation;
        int[,] Max;
        int[] Available;
        int[,] Need;
        int[] Require;
        string order;//輸出安全序列

        public Form1()
        {
            InitializeComponent();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            n = Convert.ToInt32( tb_proNum.Text);
            m = Convert.ToInt32(tb_resouseClass.Text);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (rb_allocation.Checked)
            {
                tb_output.Text  += "Allocation矩陣\r\n";
                string[] str = tb_datainput.Text.Split(' ');

                 Allocation = new int[n, m];
                for (int i = 0; i < n; i++)
                {
                    tb_output.Text+="\r\n";
                   string[] temp= str[i].Split(',');
                   for (int j = 0; j < m; j++)
                   {
                       Allocation[i, j] = Convert.ToInt32(temp[j]);
                       tb_output.Text += " " + Allocation[i, j];
                   }
                }
                
            }
            else if (rb_available.Checked)
            {
                tb_output.Text += "\r\nAvailable向量\r\n";
                string[] str = tb_datainput.Text.Split(',');
                Available = new int[m];
                for (int i = 0; i < m; i++)
                {
                    Available[i] = Convert.ToInt32(str[i]);
                    tb_output.Text += " " + Available[i];
                }        
            }
            else//輸入max矩陣
            {
                tb_output.Text += "\r\nMax矩陣\r\n";
                string[] str = tb_datainput.Text.Split(' ');
                Max = new int[n, m];
                
                for (int i = 0; i < n; i++)
                {
                    tb_output.Text+="\r\n";
                    string[] temp = str[i].Split(',');
                    for (int j = 0; j < m; j++)
                    {
                        Max[i, j] = Convert.ToInt32(temp[j]);
                        tb_output.Text += " " + Max[i, j];
                    }
                }
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            int PID = 0;
            bool[] finish = new bool[n];
            for (int i = 0; i < n; i++)
            {
                finish[i] = false;
            }
            if (tb_pid.Text == "")
                ;
            else
                PID = Convert.ToInt32(tb_pid.Text) ;


            int bigger_1 = 0;
            int bigger_2 = 0;
            ///計算Need矩陣///
            Need = new int[n, m];
            tb_output.Text += "\r\nNeed矩陣\r\n";
            for (int i = 0; i < n; i++)
            {
                tb_output.Text += "\r\n";
                for (int j = 0; j < m; j++)
                {
                    Need[i, j] = Max[i, j] - Allocation[i, j];
                    tb_output.Text += " " + Need[i, j];
                }
            }
            ///輸入Require///
            if (tb_require.Text == "")
            {
                Require = new int[m];
                for (int i = 0; i < m; i++)
                { Require[i] = 0; }
                PID = 0;
                tb_output.Text += "\r\n檢測當前狀態是否安全中…\r\n";
                if (CheckSecure(Available, finish, Need, Allocation))
                {
                    tb_output.Text += "系統目前安全"+"安全序列"+order;
                }
                else
                {
                    tb_output.Text += "系統目前不安全";

                }
            }
            else
            {
                string[] str = tb_require.Text.Split(',');
                Require = new int[m];
                for (int i = 0; i < m; i++)
                {
                    Require[i] = Convert.ToInt32(str[i]);
                    if (Require[i] > Need[PID, i])
                        bigger_1++;
                    if (Require[i] > Available[i])
                        bigger_2++;

                }

                ///檢查///
                if (bigger_1 != 0)
                {
                    tb_output.Text += "\r\n錯誤:程序申請的資源多於說明的最大量,系統無法滿足\r\n";
                }
                else if (bigger_2 != 0)
                {
                    tb_output.Text += "\r\n程序" + tb_pid.Text + "暫時阻塞\r\n";
                }
                else
                {
                    int[] temp_available = Available;
                    int[,] temp_allocation = Allocation;
                    int[,] temp_need = Need;

                    for (int j = 0; j < m; j++)
                    {
                        temp_available[j] -= Require[j];
                        temp_allocation[PID, j] += Require[j];
                        temp_need[PID, j] -= Require[j];

                    }

                    if (CheckSecure(temp_available, finish, temp_need, temp_allocation))
                    {
                        Available = temp_available;
                        Allocation = temp_allocation;
                        Need = temp_need;
                        tb_output.Text += "\r\n系統處於安全狀態,且已經分配完畢\r\n"+"安全序列"+order ;

                    }
                    else
                    { tb_output.Text += "\r\n該請求將導致系統處於不安全狀態,已經撤銷分配\r\n"; }

                }
            }
        }
///檢查安全狀態///
 public bool CheckSecure(int[] work,bool[] finish,int[,] temp_need,int[,] temp_allocation)
        {
            int num = 0;//need[i]<=work[i]的個數
            order ="";
            int[] wor = work;
            bool[] finis = finish;
            int[,] temp_nee = temp_need;
            int[,] temp_allocatio = temp_allocation;
int K=0;
while (K < 10)
{
    for (int i = 0; i < n; i++)
    {
        if (!finis[i])
        {
            for (int j = 0; j < m; j++)
            {
                if (temp_nee[i, j] <= wor[j])
                    num++;

            }
            if (num == m)
            {
                for (int j = 0; j < m; j++)
                {
                    wor[j] += temp_allocatio[i, j];
                }
                finis[i] = true;
                order += i;
                
                num = 0;

            }
            else num = 0;


        }
        else
            if (checkFinish(finis))
                return true;

    }
    K++;
} 
               

            if (checkFinish(finis))
            
                return true;
            
            else
                return false;
            }

            public bool checkFinish(bool[] f)
            {int num=0;
                foreach (bool k in f)
                {
                    if (k)
                        num++;
                    
                }
                if (num == f.Length)
                    return true;
                else return false;
            } 
    }
}
計算效果如下:


3.總結

實現功能

允許輸入資料(只輸入Available,Max,Allocation即可,Need可以自動計算,矩陣同一行元素之間用“,”隔開,換行時用空格隔開)

使用銀行家演算法進行安全檢查(若未提出請求,則應使程序號與Require後面的textbox內容為空,點選“提出請求”按鈕即可檢查當前系統安全狀態)

輸出狀態結果

輸出安全序列(注:輸出的是程序號,預設序號從0開始)

不足之處

未寫出完整的約束

不能輸出分配成功後的系統狀態

互動不夠人性化,例如沒有在輸出文字框中加入滾動條,不方便使用者檢視結果

問題

例子中經過程式計算後的need矩陣中出現了負數,不知道是為什麼,正在排查錯誤。

關鍵點

——向量比較:銀行家演算法中的向量大小比較與數學中的向量大小比較(範數比較)不同,只有向量a中的所有分量均大於向量b,才可以稱為向量a大於向量b。向量比較主要用在檢查Require是否合法,本例中使用for迴圈對於兩向量的各個分量進行比較,設定一個初始值為0的訊號變數,若任一分量小於對應分量,則將訊號變數++,迴圈結束後只需要檢查訊號變數是否為0即可知道是否前者大於後者。

——矩陣輸入:使用split方法,將字串按照給定符號(char,char[])分隔開,並賦給一個給定大小的陣列,在本例中使用逗號和空格分開了不同列不同行的元素,定義全域性變數m與n,在給陣列賦值前需要使用mn初始化陣列大小。

——使用臨時變數代替真實變數,方便恢復變數數值。因為銀行家演算法中,若資源分配後系統不安全,要求系統必須撤銷所有分配,所以使用臨時變數可以避免大量的恢復運算,即使經過檢查後,系統為安全狀態,也只需要將臨時變數的值賦給真實變數即可。

相關推薦

[C#]銀行家演算法實現

1.死鎖 死鎖,顧名思義,是一種鎖住不可自行解開的死局。 在作業系統中,“死鎖”用於描述資源分配時,程序互相搶佔資源,又因為需求的資源被別的程序搶佔,只好互相等待,以至於等待迴圈中的所有程序均無法正常執行的情況。 死鎖形成需要四個條件,這四個條件缺少一個,就不會形成死鎖。

【作業系統】銀行家演算法實現C語言)

# 【作業系統】銀行家演算法實現(C語言) ##### 注意:本人編碼水平很菜。算是自己的一個總結。可能會有我還沒有發現的bug。如果有人發現後可以指出,不勝感激。 ## 1.銀行家演算法: > 我們可以把作業系統看作是銀行家,作業系統管理的資源相當於銀行家管理的資金,程序向作業系統請求分配資源相當於

銀行家演算法實現

#include <iostream> using namespace std; #define n 4 //程序數 #define m 3//資源種類數 typedef struct{ int resource[m]; //不變 int avaliable[m]; int

Z字形掃描C語言演算法實現

#include<stdio.h> #include<stdlib.h> #define RIGHT 1 #define DOWN 2 #define LEFTDOWN 3 #define RIGHTUP 4 int main() {

快速排序演算法c語言演算法實現)-------精簡原理分析

    “快速排序法”使用的是遞迴原理,下面我結合一個例子來說明“快速排序法”的原理。首先給出一個數組{53,12,98,63,18,72,80,46, 32,21},先找到第一個數--53,把它作為中間值,也就是說,要把53放在一個位置,使得它左邊的值比它小,右邊的值比它大。{21,12,32, 46,18

C++Dijkastra演算法實現

Dijkastra演算法的主要思想是: 將頂點分為兩組,一組為使用過的頂點S,另一組為未使用過的頂點U,假設起始頂點為v,dist[]為v距離各其它頂點的最短距離,每次迭代選取未使用過且路徑最短的頂點加入S,並以此頂點為pre頂點繼續尋找其它最短路段,直至

【作業系統】小型銀行家演算法實現

一.銀行家演算法簡介:      銀行家演算法是一種避免死鎖的演算法。在避免死鎖方法中允許程序動態地申請資源,但系統在進行資源分配之前,應先j檢查並計算此次分配資源的安全性,若分配不恰當會導致導致系統進入不安全狀態,則等待.如果處於安全狀態則分配。     輸入一些資源

c++實現銀行家演算法

大三上學期的時候自己寫的銀行家演算法的程式碼,複製貼上到編譯器即可執行,希望幫助到其他人! /* Financier algorithm.(銀行家演算法) */ //=====<head file>==================

避免死鎖的銀行家演算法C++程式實現

 本篇博文為追憶曾經寫過的算法系列第二篇(20081021) 溫故知新 目的:具有代表性的死鎖避免演算法是Dijskstra給出的銀行家演算法。本實驗是基於銀行家演算法的思想通過編寫C++程式實現銀行家演算法的計算機程式化,使其更實用。同時也加深了有關自願申請、避免死

銀行家演算法——死鎖避免(C++程式碼實現

安全狀態如果存在一個安全序列,那麼系統處於安全狀態。對於程序順序<P1,P2,...,Pn>,有如下            Pi-need <= Pj-hold + All-available則這一順序為安全序列。可以保證所有程序按此順序執行後,資源分配不會

資料結構與演算法 二分法查詢【Python與C】的實現

程式碼如下: Python: def ErFen(List ,Number ,Len): left = 0 high = Len - 1 while left <= high: mid = (left + high)//2

A*演算法實現(圖形化表示)——C++描述

概要   A*演算法是一種啟發式尋路演算法,BFS是一種盲目的無目標的搜尋演算法,相比於BFS,A*演算法根據適應度構建優先佇列,根據適應度值可以很好的向目標點移動,具體詳情,請看搜尋相關文件,我在只是實現了在無障礙的情況下的A*演算法,有障礙的情況類似。 開發環境   visual studio 20

[計算機程式設計C++] Fibonaci數列的遞迴與非遞迴演算法實現

本文是對西安交通大學C++慕課第三章程式設計練習的16題的講解。 參考部落格:https://blog.csdn.net/zombie_slicer/article/details/38871799 題目內容: 編寫程式,顯示Fibonaci序列的前n項(從

GSM A5/1演算法C語言程式碼實現和分析

介紹 全球超過200個國家和地區超過10億人正在使用GSM電話。對中國使用者來說,GSM就是移動和聯通的2g模式。 在1982年A5首次提出時,人們認為A5 / 1金鑰長度要128位,但最終確定的結果是64位金鑰(政府可以使用暴力破解算出)。很可能是政府的壓力迫使金鑰位數縮

演算法實現:歸併(合併)排序(C/C++、Python)

合併排序的關鍵步驟在於合併步驟中的合併兩個已排序子序列。為做合併,引入一個輔助過程MERGE(A, p, q, r), 其中A是一個數組,p、q和r是下標,滿足p小於等於q小於r。該過程假設子陣列A[p...q] 和A[q+1...r]都已排好序,並將它們合併成一個已排好序的子陣列代替當前子陣列

演算法實現:插入排序(C/C++、Python)

虛擬碼: INSERTION-SORT for j <- 2 to length[A] key <- A[j] Insert A[j]into the sorted sequence A[l...j-1]. i <- j - 1 wh

C++單鏈表基本演算法實現

C++單鏈表基本演算法實現 #ifndef LinkList_h #define LinkList_h #include <iostream>using namespace std; template <class T> struct Node{ T data;

C++ 靜態連結串列基本演算法實現

C++ 靜態連結串列基本演算法實現 #ifndef StaticLinkList_h #define StaticLinkList_h const int MAXSIZE = 100; template <class T> struct StaticNode{ T data;

C++ 順序棧基本演算法實現

C++ 順序棧基本演算法 #ifndef SeqStack_h #define SeqStack_h #include <iostream> using namespace std; const int StackSize = 1024; template <class T>

C++ 鏈棧 基本演算法實現

C++ 鏈棧 基本演算法實現 #ifndef LinkStack_h #define LinkStack_h #include <iostream> template <class T> struct Node{ T data; struct Node <