您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)C#如何實(shí)現(xiàn)銀行家算法的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
死鎖,顧名思義,是一種鎖住不可自行解開的死局。
在操作系統(tǒng)中,“死鎖”用于描述資源分配時(shí),進(jìn)程互相搶占資源,又因?yàn)樾枨蟮馁Y源被別的進(jìn)程搶占,只好互相等待,以至于等待循環(huán)中的所有進(jìn)程均無法正常運(yùn)行的情況。
死鎖形成需要四個(gè)條件,這四個(gè)條件缺少一個(gè),就不會(huì)形成死鎖。
死鎖的四個(gè)條件
1)互斥條件
即對(duì)于某資源在一段時(shí)間內(nèi)僅允許一個(gè)進(jìn)程占有使用。
2)占有且等待條件/請(qǐng)求和保持條件
在進(jìn)程已經(jīng)占有一個(gè)或多個(gè)資源的情況下,若它仍申請(qǐng)新的資源,在等待獲得新的資源時(shí),進(jìn)程仍會(huì)繼續(xù)占有舊有資源,不會(huì)主動(dòng)釋放。
3)不可搶占條件
直到占有該資源的進(jìn)程使用完畢之前,其他任何進(jìn)程均不應(yīng)該強(qiáng)行搶占該資源。
4)循環(huán)等待條件
若干個(gè)進(jìn)程之間形成了一個(gè)等待循環(huán)。
若針對(duì)目前資源分配情況,系統(tǒng)可以找到某種次序?yàn)檫M(jìn)程分配資源,使得所有進(jìn)程能夠依次運(yùn)行成功,則稱系統(tǒng)此時(shí)的分配狀態(tài)是安全的,分配資源的次序稱為“安全序列”。
安全狀態(tài)時(shí)系統(tǒng)中無死鎖,所以所有避免死鎖的算法都盡可能地使系統(tǒng)進(jìn)入安全狀態(tài)。
值得注意的是,即使是安全狀態(tài)下的系統(tǒng),如果資源分配不當(dāng),仍然可以使系統(tǒng)變?yōu)椴话踩珷顟B(tài)。
1)設(shè)計(jì)思想
在系統(tǒng)中,進(jìn)程發(fā)起一項(xiàng)資源分配請(qǐng)求,由系統(tǒng)檢查是否可以滿足該分配請(qǐng)求,若可以,應(yīng)暫時(shí)滿足該請(qǐng)求,并查看此時(shí)系統(tǒng)是否仍是安全狀態(tài)。
2)程序流程圖
可以分為三個(gè)功能模塊,第一個(gè)模塊檢查需求是否可以被滿足,第二個(gè)模塊檢查系統(tǒng)是否安全,第三個(gè)模塊是主程序,通過調(diào)用前兩個(gè)模塊實(shí)現(xiàn)資源分配或請(qǐng)求駁回。
3)數(shù)據(jù)結(jié)構(gòu)
設(shè)有m種資源,n個(gè)進(jìn)程。
int[] Available[m] 系統(tǒng)內(nèi)可用資源
int[,] Max[n,m] 進(jìn)程對(duì)每種資源的最大需求
int[,] Allocation[n,m] 已分配給各個(gè)進(jìn)程的資源
int[,] Need[n,m] 目前各個(gè)進(jìn)程對(duì)各個(gè)資源的需求數(shù)
[顯然有Need=Max-Allocation]
int[,] Require[m] 對(duì)于各種資源的請(qǐng)求函數(shù)
bool[] Finish[n] 進(jìn)程是否可以成功運(yùn)行的標(biāo)志
int[] Work[m] 用于分配資源的向量
[定義:Work=Available-Require]
4)窗體設(shè)計(jì)
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;//進(jìn)程數(shù)目 public int m = 1;//資源分類數(shù) 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; ///計(jì)算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檢測(cè)當(dāng)前狀態(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錯(cuò)誤:進(jìn)程申請(qǐng)的資源多于說明的最大量,系統(tǒng)無法滿足\r\n"; } else if (bigger_2 != 0) { tb_output.Text += "\r\n進(jìn)程" + tb_pid.Text + "暫時(shí)阻塞\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),且已經(jīng)分配完畢\r\n"+"安全序列"+order ; } else { tb_output.Text += "\r\n該請(qǐng)求將導(dǎo)致系統(tǒng)處于不安全狀態(tài),已經(jīng)撤銷分配\r\n"; } } } } ///檢查安全狀態(tài)/// public bool CheckSecure(int[] work,bool[] finish,int[,] temp_need,int[,] temp_allocation) { int num = 0;//need[i]<=work[i]的個(gè)數(shù) 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; } } }
計(jì)算效果如下:
實(shí)現(xiàn)功能
允許輸入數(shù)據(jù)(只輸入Available,Max,Allocation即可,Need可以自動(dòng)計(jì)算,矩陣同一行元素之間用“,”隔開,換行時(shí)用空格隔開)
使用銀行家算法進(jìn)行安全檢查(若未提出請(qǐng)求,則應(yīng)使進(jìn)程號(hào)與Require后面的textbox內(nèi)容為空,點(diǎn)擊“提出請(qǐng)求”按鈕即可檢查當(dāng)前系統(tǒng)安全狀態(tài))
輸出狀態(tài)結(jié)果
輸出安全序列(注:輸出的是進(jìn)程號(hào),默認(rèn)序號(hào)從0開始)
不足之處
未寫出完整的約束
不能輸出分配成功后的系統(tǒng)狀態(tài)
交互不夠人性化,例如沒有在輸出文本框中加入滾動(dòng)條,不方便使用者查看結(jié)果
問題
例子中經(jīng)過程序計(jì)算后的need矩陣中出現(xiàn)了負(fù)數(shù),不知道是為什么,正在排查錯(cuò)誤。
關(guān)鍵點(diǎn)
——向量比較:銀行家算法中的向量大小比較與數(shù)學(xué)中的向量大小比較(范數(shù)比較)不同,只有向量a中的所有分量均大于向量b,才可以稱為向量a大于向量b。向量比較主要用在檢查Require是否合法,本例中使用for循環(huán)對(duì)于兩向量的各個(gè)分量進(jìn)行比較,設(shè)置一個(gè)初始值為0的信號(hào)變量,若任一分量小于對(duì)應(yīng)分量,則將信號(hào)變量++,循環(huán)結(jié)束后只需要檢查信號(hào)變量是否為0即可知道是否前者大于后者。
——矩陣輸入:使用split方法,將字符串按照給定符號(hào)(char,char[])分隔開,并賦給一個(gè)給定大小的數(shù)組,在本例中使用逗號(hào)和空格分開了不同列不同行的元素,定義全局變量m與n,在給數(shù)組賦值前需要使用mn初始化數(shù)組大小。
——使用臨時(shí)變量代替真實(shí)變量,方便恢復(fù)變量數(shù)值。因?yàn)殂y行家算法中,若資源分配后系統(tǒng)不安全,要求系統(tǒng)必須撤銷所有分配,所以使用臨時(shí)變量可以避免大量的恢復(fù)運(yùn)算,即使經(jīng)過檢查后,系統(tǒng)為安全狀態(tài),也只需要將臨時(shí)變量的值賦給真實(shí)變量即可。
感謝各位的閱讀!關(guān)于“C#如何實(shí)現(xiàn)銀行家算法”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。