銀行家算法模擬
我們可以把操作系統看作是銀行家,操作系統管理的資源相當於銀行家管理的資金,進程向操作系統請求分配資源相當於用戶向銀行家貸款。
爲保證資金的安全,銀行家規定:
(1) 當一個顧客對資金的最大需求量不超過銀行家現有的資金時就可接納該顧客;
(2) 顧客可以分期貸款,但貸款的總數不能超過最大需求量;
(3) 當銀行家現有的資金不能滿足顧客尚需的貸款數額時,對顧客的貸款可推遲支付,但總能使顧客在有限的時間裏得到貸款;
(4) 當顧客得到所需的全部資金後,一定能在有限的時間裏歸還所有的資金.
銀行家算法數據結構
1)可利用資源向量Available
是個含有m個元素的數組,其中的每一個元素代表一類可利用的資源數目。如果Available[j]=K,則表示系統中現有Rj類資源K個。
2)最大需求矩陣Max
這是一個n×m的矩陣,它定義了系統中n個進程中的每一個進程對m類資源的最大需求。如果Max[i,j]=K,則表示進程i需要Rj類資源的最大數目爲K。
3)分配矩陣Allocation
這也是一個n×m的矩陣,它定義了系統中每一類資源當前已分配給每一進程的資源數。如果Allocation[i,j]=K,則表示進程i當前已分得Rj類資源的 數目爲K。
4)需求矩陣Need。
這也是一個n×m的矩陣,用以表示每一個進程尚需的各類資源數。如果Need[i,j]=K,則表示進程i還需要Rj類資源K個,方能完成其任務。
Need[i,j]=Max[i,j]-Allocation[i,j]
算法 的實現
一、初始化
由用戶輸入數據,分別對可利用資源向量矩陣AVAILABLE 、 最大需求矩陣MAX 、分配矩陣ALLOCATION、 需求矩陣NEED 賦值。
二、銀行家算法
在避免死鎖的方法中,所施加的限制條件較弱,有可能獲得令人滿意的系統性能。在該方法中把系統的狀態分爲安全狀態和不安全狀態,只要能使系統始終都處於安全狀態,便可以避免發生死鎖。
銀行家算法的基本思想是分配資源之前, 判斷系統是否是安全的; 若是, 才分配。它是最具有 代表性的避免死鎖的算法。
設進程cusneed 提出請求REQUEST [i] ,則銀行家算法按如下規則進行判斷。
(1) 如果REQUEST [cusneed] [i]<= NEED[cusneed][i] ,則轉(2) ;否則,出錯。
(2) 如果REQUEST [cusneed] [i]<= AVAILABLE[cusneed][i] ,則轉(3) ;否則,出錯。
(3) 系統試探分配資源,修改相關數據:
AVAILABLE[i]-=REQUEST[cusneed][i];
ALLOCATION[cusneed][i]+=REQUEST[cusneed][i];
NEED[cusneed][i]-=REQUEST[cusneed][i];
(4) 系統執行安全性檢查,如安全,則分配成立;否則試探險性分配作廢,系統恢復 原狀, 進程等待。
三、安全性檢查算法
(1) 設置兩個工作向量Work=AVAILABLE;FINISH
(2) 從進程集合中找到一個滿足下述條件的進 程,
FINISH==false;
NEED<=Work;
如找到,執行(3) ; 否則,執行(4)
(3) 設進程獲得資源,可順利執行,直至完 成,從而釋放資源。
Work+=ALLOCATION;
Finish=true;
GOTO 2
(4) 如所有的進程Finish= true ,則表 示安全;否則系統不安全。
操作系統安全狀態和不安全狀態:
安全序列是指一個進程序列{P1,…,Pn}是安全的,如果對於每一個進程Pi(1≤i≤n),它以後尚需要的資源量不超過系統當前剩餘資源量與所有進程Pj (j < i )當前佔有資源
量之和。
如果存在一個由系統中所有進程構成的安全序列P1,…,Pn,則系統處於安全狀態。安全狀態一定是沒有死鎖發生。
不存在一個安全序列。不安全狀態不一定導致死鎖。
各算法流程圖
初始化算法流程圖:
銀行家算法流程圖:
安全性算法流程 圖:
package Banker;
import java.util.Scanner;
public class Banker {
/**
* @param args
*/
int MAXPROCESS =50; /*最大進程數*/
int MAXRESOURCE =100; /*最大資源數*/
int m,n; /*m個進程,n個資源*/
int[][] MAX;
int[][] ALLOCATION ;
int[][] NEED ;
int[] AVAILABLE ;
int[][] REQUEST ;
int[] p ;
boolean[] FINISH ;
public void Init() /*初始化算法*/
{
int i,j;
Scanner in = new Scanner(System.in);
System.out.println("請輸入進程的數目:");
m=in.nextInt();
System.out.println("請輸入資源的種類:");
n=in.nextInt();
System.out.println("請輸入每個進程最多所需的各資源數,按照"+m+"x"+n+"矩 陣輸入");
MAX =new int[m][n];
for(i=0;i<m;i++) {
for(j=0;j<n;j++) {
MAX[i][j]=in.nextInt();
}}
System.out.println("請輸入每個進程已分配的各資源數,也按照"+m+"x"+n+"矩 陣輸入");
ALLOCATION=new int[m][n];
NEED=new int[m][n];
AVAILABLE=new int[n];
REQUEST=new int[m][n];
p=new int[m];
FINISH=new boolean[m];
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
ALLOCATION[i][j]=in.nextInt();
NEED[i][j]=MAX[i][j]-ALLOCATION[i][j];
if(NEED[i][j]<0)
{
System.out.println("您輸入的第"+i+1+"個進程所擁有的第"+j+1+"個資源數 錯誤,請重新輸入:");
j--;
continue;
}
}
}
System.out.println("請輸入各個資源現有的數目:");
for(i=0;i<n;i++)
{
AVAILABLE[i]=in.nextInt();
}
}
void Bank() /*銀行家算法*/
{
Scanner in = new Scanner(System.in);
int i,cusneed,flag = 0;
char again;
while(true)
{
showdata(n,m);////////////////////////////////////////////////////////////////////
System.out.println("請輸入要申請資源的進程號(注:第1個進程號爲0,依次類推)");
int cusneed1=in.nextInt();
if (cusneed1 > m)
{
System.out.println("沒有該進程,請重新輸入");
}
System.out.println("請輸入進程所請求的各資源的數量");
for(i=0;i<n;i++)
{
REQUEST[cusneed1][i]=in.nextInt();
}
for(i=0;i<n;i++)
{
if(REQUEST[cusneed1][i]>NEED[cusneed1][i])//如果用戶選擇的線程的第i個資源請求數>該線程該資源所需的數量
{
System.out.println("您輸入的請求數超過進程的需求量!請重新輸入!");
}
if(REQUEST[cusneed1][i]>AVAILABLE[i])//如果用戶選擇的線程的第i個資源請求數>系統現有的第i個資源的數量
{
System.out.println("您輸入的請求數超過系統有的資源數!請重新輸入!");
}
}
for(i=0;i<n;i++)//如果請求合理,那麼下面
{
AVAILABLE[i]-=REQUEST[cusneed1][i];//系統可用資源減去申請了的
ALLOCATION[cusneed1][i]+=REQUEST[cusneed1][i];//線程被分配的資源加上已申請了的
NEED[cusneed1][i]-=REQUEST[cusneed1][i];//線程還需要的資源減去已申請得到的
}
if(Safe())//AVAILABLE ALLOCATION NEED變動之後,是否會導致不安全
{
System.out.println("同意分配請求!");
}
else
{
System.out.println("您的請求被拒絕!");
for(i=0;i<n;i++)
{
AVAILABLE[i]+=REQUEST[cusneed1][i];
ALLOCATION[cusneed1][i]-=REQUEST[cusneed1][i];
NEED[cusneed1][i]+=REQUEST[cusneed1][i];
}
}
for (i=0;i<n;i++)
{
if (NEED[cusneed1][i] <= 0)
{
flag++;
}
}
if (flag == n)//如果該進程各資源都已滿足條件,則釋放資源
{
for (i=0;i<n;i++)
{
AVAILABLE[i] += ALLOCATION[cusneed1][i];
ALLOCATION[cusneed1][i] = 0;
NEED[cusneed1][i] = 0;
}
System.out.println("線程"+cusneed1+" 佔有的資源被釋放!");
flag = 0;
}
for(i=0;i<m;i++)//分配好了以後將進程的標識FINISH改成false
{
FINISH[i]=false;
}
System.out.println("您還想再次請求分配嗎?是請按y/Y,否請按其它鍵");
again=(char) in.nextInt();
if(again=='y'||again=='Y')
{
continue;
}
break;
}
}
public Boolean Safe() /*安全性算法*/
{
int i,j,k,l=0;
int[] Work =new int[MAXRESOURCE]; /*工作數組*/
for(i=0;i<n;i++)
Work[i]=AVAILABLE[i];
for(i=0;i<m;i++)
{
FINISH[i]=false;//FINISH記錄每個進程是否安全
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)//循環查找第i個進程需要的各個資源數 是否 超過系統現有的對應的資源數
{
if(NEED[i][j]>Work[j])//第i個進程需要的第j個資源數 > 系統現有的第j個資源數
{
break;
}
}
if(j==n)//如果第i個進程所需的各個資源數都沒有超過系統現有的對應資源數
{
FINISH[i]=true;//給該進程的FINISH標記爲true
for(k=0;k<n;k++)
{
Work[k]+=ALLOCATION[i][k];//將Work賦值爲 第i個進程各個已分配資源數+系統現有的對應資源數(因爲當改進程全部資源數都滿足時線程結束並將資源返還給系統)
}
p[l++]=i;//記錄進程號
}
else//如果超過繼續循環下一個進程
{
continue;
}
if(l==m)//當所有進程都能夠被滿足運行時
{
System.out.println("系統是安全的");
System.out.println("安全序列:");
for(i=0;i<l;i++)//改了146行的i值,顯示資源分配給進程的順序
{
System.out.println(p[i]);
if(i!=l-1)
{
System.out.println("-->");
}
}
System.out.println("");
return true;
}
}//for循環
System.out.println("系統是不安全的");
return false;
}
void showdata(int n,int m) //顯示
{
int i,j;
System.out.println();
System.out.println("-------------------------------------------------------------");
System.out.println("系統可用的資源數爲: ");
for (j=0;j<n;j++)
System.out.println(" "+AVAILABLE[j]);
System.out.println();
System.out.println("各進程還需要的資源量:");
for (i=0;i<m;i++)
{
System.out.println(" 進程"+i+":");
for (j=0;j<n;j++)
System.out.println(" "+NEED[i][j]);
}
System.out.println("各進程已經得到的資源量: ");
for (i=0;i<m;i++)
{
System.out.println(" 進程"+i+":");
for (j=0;j<n;j++)
System.out.println(" "+ALLOCATION[i][j]);
System.out.println();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Banker Bank=new Banker();
Bank.Init();
Bank.Safe();
Bank.Bank();
}