C#實現銀行家算法
本文實例為大家分享了C#實現銀行家算法的具體代碼,供大家參考,具體內容如下
1.死鎖
死鎖,顧名思義,是一種鎖住不可自行解開的死局。
在操作系統(tǒng)中,“死鎖”用于描述資源分配時,進程互相搶占資源,又因為需求的資源被別的進程搶占,只好互相等待,以至于等待循環(huán)中的所有進程均無法正常運行的情況。
死鎖形成需要四個條件,這四個條件缺少一個,就不會形成死鎖。
死鎖的四個條件
1)互斥條件
即對于某資源在一段時間內僅允許一個進程占有使用。
2)占有且等待條件/請求和保持條件
在進程已經占有一個或多個資源的情況下,若它仍申請新的資源,在等待獲得新的資源時,進程仍會繼續(xù)占有舊有資源,不會主動釋放。
3)不可搶占條件
直到占有該資源的進程使用完畢之前,其他任何進程均不應該強行搶占該資源。
4)循環(huán)等待條件
若干個進程之間形成了一個等待循環(huán)。
2.安全狀態(tài)
若針對目前資源分配情況,系統(tǒng)可以找到某種次序為進程分配資源,使得所有進程能夠依次運行成功,則稱系統(tǒng)此時的分配狀態(tài)是安全的,分配資源的次序稱為“安全序列”。
安全狀態(tài)時系統(tǒng)中無死鎖,所以所有避免死鎖的算法都盡可能地使系統(tǒng)進入安全狀態(tài)。
值得注意的是,即使是安全狀態(tài)下的系統(tǒng),如果資源分配不當,仍然可以使系統(tǒng)變?yōu)椴话踩珷顟B(tài)。
3.銀行家算法
1)設計思想
在系統(tǒng)中,進程發(fā)起一項資源分配請求,由系統(tǒng)檢查是否可以滿足該分配請求,若可以,應暫時滿足該請求,并查看此時系統(tǒng)是否仍是安全狀態(tài)。
2)程序流程圖
可以分為三個功能模塊,第一個模塊檢查需求是否可以被滿足,第二個模塊檢查系統(tǒng)是否安全,第三個模塊是主程序,通過調用前兩個模塊實現資源分配或請求駁回。


3)數據結構
設有m種資源,n個進程。
int[] Available[m] 系統(tǒng)內可用資源
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檢測當前狀態(tài)是否安全中…\r\n";
if (CheckSecure(Available, finish, Need, Allocation))
{
tb_output.Text += "系統(tǒng)目前安全"+"安全序列"+order;
}
else
{
tb_output.Text += "系統(tǒng)目前不安全";
}
}
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錯誤:進程申請的資源多于說明的最大量,系統(tǒng)無法滿足\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系統(tǒng)處于安全狀態(tài),且已經分配完畢\r\n"+"安全序列"+order ;
}
else
{ tb_output.Text += "\r\n該請求將導致系統(tǒng)處于不安全狀態(tài),已經撤銷分配\r\n"; }
}
}
}
///檢查安全狀態(tài)///
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內容為空,點擊“提出請求”按鈕即可檢查當前系統(tǒng)安全狀態(tài))
輸出狀態(tài)結果
輸出安全序列(注:輸出的是進程號,默認序號從0開始)
不足之處
未寫出完整的約束
不能輸出分配成功后的系統(tǒng)狀態(tài)
交互不夠人性化,例如沒有在輸出文本框中加入滾動條,不方便使用者查看結果
問題
例子中經過程序計算后的need矩陣中出現了負數,不知道是為什么,正在排查錯誤。
關鍵點
——向量比較:銀行家算法中的向量大小比較與數學中的向量大小比較(范數比較)不同,只有向量a中的所有分量均大于向量b,才可以稱為向量a大于向量b。向量比較主要用在檢查Require是否合法,本例中使用for循環(huán)對于兩向量的各個分量進行比較,設置一個初始值為0的信號變量,若任一分量小于對應分量,則將信號變量++,循環(huán)結束后只需要檢查信號變量是否為0即可知道是否前者大于后者。
——矩陣輸入:使用split方法,將字符串按照給定符號(char,char[])分隔開,并賦給一個給定大小的數組,在本例中使用逗號和空格分開了不同列不同行的元素,定義全局變量m與n,在給數組賦值前需要使用mn初始化數組大小。
——使用臨時變量代替真實變量,方便恢復變量數值。因為銀行家算法中,若資源分配后系統(tǒng)不安全,要求系統(tǒng)必須撤銷所有分配,所以使用臨時變量可以避免大量的恢復運算,即使經過檢查后,系統(tǒng)為安全狀態(tài),也只需要將臨時變量的值賦給真實變量即可。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
關于C#操作文件路徑(Directory)的常用靜態(tài)方法詳解
這篇文章主要給大家介紹了關于C#操作文件路徑(Directory)的常用靜態(tài)方法,Directory類位于System.IO 命名空間,Directory類提供了在目錄和子目錄中進行創(chuàng)建移動和列舉操作的靜態(tài)方法,需要的朋友可以參考下2021-08-08
C# 并發(fā)控制框架之單線程環(huán)境下實現每秒百萬級調度
本文介紹了一款專為工業(yè)自動化及機器視覺開發(fā)的C#并發(fā)流程控制框架,通過模仿Go語言并發(fā)模式設計,支持高頻調度及復雜任務處理,已在多個項目中驗證其穩(wěn)定性和可靠性2024-10-10

