Java~操作系統實驗銀行家算法的實現(附帶源碼)

一、實驗內容

銀行家算法的實現。

二、實驗目的

銀行家算法是一種最有代表性的避免死鎖的算法。在避免死鎖方法中允許進程動態地申請資源,但系統在進行資源分配之前,應先計算此次分配資源的安全性,若分配不會導致系統進入不安全狀態,則分配,否則等待。通過編寫一個模擬動態資源分配的銀行家算法程序,幫助學生進一步深入理解死鎖、產生死鎖的必要條件、安全狀態等重要概念,並掌握避免死鎖的具體實施方法。

三、實驗原理

3.1、銀行家算法中的數據結構

1)可利用資源向量Available
是個含有m個元素的數組,其中的每一個元素代表一類可利用的資源數目。如果Available[j]=K,則表示系統中現有Rj類資源K個。

Resources[] Available = new Resources[resKindNum];//系統總資源

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]

//進程的數據結構
class PCB {
    public String name;
    public Resources[] max;//最大需求資源Max
    public Resources[] allocation;//已分配資源Allocation
    public Resources[] need;//需求資源Need
    public boolean finish = false;//表示進程是否獲得足夠資源

    public PCB(String name, Resources[] max, Resources[] allocation) {
        this.name = name;
        this.max = max;
        this.allocation = allocation;
        this.need = new Resources[max.length];
        for (int i = 0; i < need.length; i++) {
            this.need[i] = new Resources(max[i].name, max[i].num - allocation[i].num);
        }
    }

    @Override
    public String toString() {
        return this.name +(this.finish ? "進程已得到足夠資源" : "需要等待");
    }
}

3.2、銀行家算法

設Requesti是進程Pi的請求向量,如果Requesti[j]=K,表示進程Pi需要K個Rj類型的資源。當Pi發出資源請求後,系統按下述步驟進行檢查:
(1)如果Requesti[j]≤Need[i,j],便轉向步驟(2);否則認爲出錯,因爲它所需要的資源數已超過它所宣佈最大值。
(2)如果Requesti[j]≤Available[j],便轉向步驟(3);否則,表示尚無足夠資源,Pi須等待。

private boolean needWait(PCB pcb) {
        //挨個判斷此時pcb這個進程所需要的每個資源,如果need大於系統當前可分配資源,就說明需要等待
        for (int i = 0; i < this.work.length; i++) {
            if (this.work[i].num < pcb.need[i].num) {
                return true;
            }
        }
        return false;
    }

(3)系統試探着把資源分配給進程Pi,並修改下面數據結構中的數值:
Available[j]=Available[j]-Requesti[j];
Allocation[i,j]=Allocation[i,j]+Requesti[j];
Need[i,j]=Need[i,j]-Requesti[j];
系統執行安全性算法,檢查此次資源分配後,系統是否處於安全狀態。若安全,才正式將資源分配給進程Pi,以完成本次分配;否則,將本次的試探分配作廢,恢復原來的資源分配狀態,讓進程Pi等待。

 //進行資源分配
    public void resAllocation() {
        //對進程進行循環資源分配,當所有進程都需要等待或者所有進程都爲安全狀態退出循環
        for (int i = 0; !ifSafe() && !ifAllNeedWait(); i++) {
            //實現循環
            if (i == this.pcbs.length) {
                i = 0;
            }
            //判斷當前這個進程是否已經獲得過足夠資源
            if (pcbs[i].finish) {
                continue;
            }
            //判斷當前這個進程是否需要等待
            if (! needWait(pcbs[i])) {
                //進行資源分配
                mainOperation(pcbs[i]);
                System.out.println(pcbs[i]);
                System.out.println();
                displayWorks();
            }
        }
        System.out.println();
        if (ifSafe()) {
            System.out.println("系統處於安全狀態");
        } else {
            System.out.println("系統處於不安全狀態");
        }
    }

3.3、安全性算法

1)設置兩個向量:
工作向量Work: 它表示系統可提供給進程繼續運行所需的各類資源數目,它含有m個元素,在執行安全算法開始時,Work=Available;
工作向量Finish: 它表示系統是否有足夠的資源分配給進程,使之運行完成。開始時先做Finish[i]=false; 當有足夠資源分配給進程時, 再令Finish[i]=true。
2)從進程集合中找到一個能滿足下述條件的進程: 
Finish[i]=false;
Need[i,j]≤Work[j];若找到,執行 (3),否則,執行 (4)
3)當進程Pi獲得資源後,可順利執行,直至完成,並釋放出分配給它的資源,故應執行:
Work[j]=Work[i]+Allocation[i,j];
Finish[i]=true;
go to step 2;

private void mainOperation(PCB pcb) {
        //運行到這說明該進程可以得到足夠的資源,那麼直接將該進程已分配的資源放回到系統中
        //並將finish改爲true
        for (int i = 0; i < this.work.length; i++) {
            this.work[i].num += pcb.allocation[i].num;
            pcb.finish = true;
        }
    }

4)如果所有進程的Finish[i]=true都滿足, 則表示系統處於安全狀態;否則,系統處於不安全狀態

四、實現代碼

//系統資源的數據結構
class Resources {
    public String name;
    public int num;

    public Resources(String name, int num) {
        this.name = name;
        this.num = num;
    }

    @Override
    public String toString() {
        return "資源"+ name  + "有" + num;
    }
}
//進程的數據結構
class PCB {
    public String name;
    public Resources[] max;//最大需求資源Max
    public Resources[] allocation;//已分配資源Allocation
    public Resources[] need;//需求資源Need
    public boolean finish = false;//表示進程是否獲得足夠資源

    public PCB(String name, Resources[] max, Resources[] allocation) {
        this.name = name;
        this.max = max;
        this.allocation = allocation;
        this.need = new Resources[max.length];
        for (int i = 0; i < need.length; i++) {
            this.need[i] = new Resources(max[i].name, max[i].num - allocation[i].num);
        }
    }

    @Override
    public String toString() {
        return this.name +(this.finish ? "進程已得到足夠資源" : "需要等待");
    }
}

public class BankerAlgorithm {
    private Resources[] work;//當前可以資源
    private PCB[] pcbs;//所有進程

    public BankerAlgorithm(Resources[] Available, PCB[] pcbs) {
        this.work = Available;//一開始可用資源與系統總資源是相同的
        this.pcbs = pcbs;
        //計算剩餘可用資源
        actualWork();
    }

    private void actualWork() {
        for (int i = 0; i < this.work.length; i++) {
            //初始系統總資源減去已分配的資源就是當前可以利用的資源
            this.work[i].num = this.work[i].num - pcbsAllRes(i);
        }
    }
    //計算所有進程已分配的第i個資源總數
    private int pcbsAllRes(int index) {
        int sum = 0;
        for ( PCB p : pcbs
             ) {
            sum += p.allocation[index].num;
        }
        return sum;
    }

    //判斷是否爲安全狀態
    private boolean ifSafe() {
        for (PCB p : pcbs
             ) {
            if (! p.finish) {
                return false;
            }
        }
        return true;
    }

    //進行資源分配
    public void resAllocation() {
        //對進程進行循環資源分配,當所有進程都需要等待或者所有進程都爲安全狀態退出循環
        for (int i = 0; !ifSafe() && !ifAllNeedWait(); i++) {
            //實現循環
            if (i == this.pcbs.length) {
                i = 0;
            }
            //判斷當前這個進程是否已經獲得過足夠資源
            if (pcbs[i].finish) {
                continue;
            }
            //判斷當前這個進程是否需要等待
            if (! needWait(pcbs[i])) {
                //進行資源分配
                mainOperation(pcbs[i]);
                System.out.println(pcbs[i]);
                System.out.println();
                displayWorks();
            }
        }
        System.out.println();
        if (ifSafe()) {
            System.out.println("系統處於安全狀態");
        } else {
            System.out.println("系統處於不安全狀態");
        }
    }

    private void displayWorks() {
        System.out.println("此時系統可用資源爲:");
        System.out.println("====================");
        for (Resources r : this.work
             ) {
            System.out.println(r);
        }
        System.out.println("====================");
    }

    private boolean ifAllNeedWait() {
        for (PCB p : this.pcbs
             ) {
            //如果該進程已經得到過足夠資源就不進行判斷
            if (!p.finish) {
                //如果該進程不需要等待就直接返回false
                if (!needWait(p)) {
                    return false;
                }
            }
        }
        return true;
    }

    private void mainOperation(PCB pcb) {
        //運行到這說明該進程可以得到足夠的資源,那麼直接將該進程已分配的資源放回到系統中
        //並將finish改爲true
        for (int i = 0; i < this.work.length; i++) {
            this.work[i].num += pcb.allocation[i].num;
            pcb.finish = true;
        }
    }

    private boolean needWait(PCB pcb) {
        //挨個判斷此時pcb這個進程所需要的每個資源,如果need大於系統當前可分配資源,就說明需要等待
        for (int i = 0; i < this.work.length; i++) {
            if (this.work[i].num < pcb.need[i].num) {
                return true;
            }
        }
        return false;
    }
}

測試數據及結果

數據

在這裏插入圖片描述



import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.print("輸入資源有幾種:");
        int resKindNum = scan.nextInt();
        Resources[] Available = new Resources[resKindNum];//系統總資源
        System.out.println();
        System.out.println("輸入每個系統資源名稱、系統資源數量");


        for (int i = 0; i < Available.length; i++) {
            System.out.println("初始化第" + (i +1) + "個資源");
            System.out.println();
            System.out.print("資源名稱:");
            String name = scan.next();
            System.out.println();
            System.out.print("該資源數量:");
            int num = scan.nextInt();
            Available[i] = new Resources(name, num);
            System.out.println();
            System.out.println("第" + (i +1) + "個資源初始化完畢");
            System.out.println("====================");
        }


        System.out.println();
        System.out.println("系統資源初始化完畢,開始初始化進程");
        System.out.println();


        System.out.print("輸入進程個數:");
        int pcbNums = scan.nextInt();
        PCB[] pcbs = new PCB[pcbNums];


        for (int i = 0; i < pcbNums; i++) {
            System.out.println("初始化第" + (i +1) + "個進程");
            System.out.println();
            System.out.print("輸入進程名:");
            String name = scan.next();
            System.out.println();
            System.out.print("輸入該進程最大需求資源:");
            Resources[] max = new Resources[resKindNum];
            int[] maxResNum = new int[resKindNum];
            for (int j = 0; j < resKindNum; j++) {
                maxResNum[j] = scan.nextInt();
            }


            for (int j = 0; j < max.length; j++) {

                max[j] = new Resources(Available[j].name, maxResNum[j]);
            }


            System.out.println();
            System.out.print("輸入該進程已分配資源數目:");
            Resources[] allocation = new Resources[resKindNum];
            int[] allocReesNum = new int[resKindNum];
            for (int j = 0; j < resKindNum; j++) {
                allocReesNum[j] = scan.nextInt();
            }

            for (int j = 0; j < allocation.length; j++) {
                allocation[j] = new Resources(Available[j].name, allocReesNum[j]);
            }
            System.out.println();


            //此時一個進程的所有需要的東西都已輸入完畢
            pcbs[i] = new PCB(name, max, allocation);
            System.out.println("第" + (i +1) + "個進程初始化完畢");
            System.out.println("====================");
        }

        System.out.println();
        System.out.println("========所有進程初始化完畢,開始資源分配========");
        System.out.println();

        boolean key = true;
        while (key) {
            BetterBankerAlgorithm bankerAlgorithm = new BetterBankerAlgorithm(Available, pcbs);
            bankerAlgorithm.resAllocation();
            System.out.println();
            System.out.println("是否需要再次申請資源輸入: y or n ");
            char ch = scan.next().charAt(0);
            if (ch == 'n' || ch == 'N') {
                key = false;
            } else {
                System.out.print("輸入要申請資源的進程名:");
                String name = scan.next();
                System.out.println();
                System.out.print("輸入要申請資源的數量:");
                int[] res = new int[resKindNum];
                for (int i = 0; i < resKindNum; i++) {
                    res[i] = scan.nextInt();
                }
                System.out.println();


                for (PCB p : pcbs
                     ) {
                    p.finish = false;
                    if (p.name.equals(name)) {
                        for (int i = 0; i < p.allocation.length; i++) {
                            p.allocation[i].num += res[i];
                        }
                    }
                }
                System.out.println();
                System.out.println("========再次申請資源完畢,開始資源分配========");
                System.out.println();
            }
        }
    }
}


結果

輸入資源有幾種:4

輸入每個系統資源名稱、系統資源數量
初始化第1個資源

資源名稱:R1

該資源數量:61個資源初始化完畢
====================
初始化第2個資源

資源名稱:R2

該資源數量:72個資源初始化完畢
====================
初始化第3個資源

資源名稱:R3

該資源數量:123個資源初始化完畢
====================
初始化第4個資源

資源名稱:R4

該資源數量:124個資源初始化完畢
====================

系統資源初始化完畢,開始初始化進程

輸入進程個數:5
初始化第1個進程

輸入進程名:P0

輸入該進程最大需求資源:0 0 1 2

輸入該進程已分配資源數目:0 0 1 21個進程初始化完畢
====================
初始化第2個進程

輸入進程名:P1

輸入該進程最大需求資源:2 7 5 0

輸入該進程已分配資源數目:2 0 0 02個進程初始化完畢
====================
初始化第3個進程

輸入進程名:P2

輸入該進程最大需求資源:6 6 5 6

輸入該進程已分配資源數目:0 0 3 43個進程初始化完畢
====================
初始化第4個進程

輸入進程名:P3

輸入該進程最大需求資源:4 3 5 6

輸入該進程已分配資源數目:2 3 5 44個進程初始化完畢
====================
初始化第5個進程

輸入進程名:P4

輸入該進程最大需求資源:0 6 5 2

輸入該進程已分配資源數目:0 3 3 25個進程初始化完畢
====================

========所有進程初始化完畢,開始資源分配========

P0進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有2
資源R2有1
資源R3有1
資源R4有2
====================
P3進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有4
資源R2有4
資源R3有6
資源R4有6
====================
P4進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有4
資源R2有7
資源R3有9
資源R4有8
====================
P1進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有6
資源R2有7
資源R3有9
資源R4有8
====================
P2進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有6
資源R2有7
資源R3有12
資源R4有12
====================

系統處於安全狀態

是否需要再次申請資源輸入: y or n 
Y
輸入要申請資源的進程名:P2

輸入要申請資源的數量:0 1 0 0


========再次申請資源完畢,開始資源分配========

P0進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有2
資源R2有0
資源R3有1
資源R4有2
====================
P3進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有4
資源R2有3
資源R3有6
資源R4有6
====================
P4進程已得到足夠資源

此時系統可用資源爲:
====================
資源R1有4
資源R2有6
資源R3有9
資源R4有8
====================

系統處於不安全狀態

是否需要再次申請資源輸入: y or n 
N

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章