[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 <