使用java實現銀行家演算法
阿新 • • 發佈:2020-01-07
銀行家演算法核心
先尋找滿足系統當前剩餘的資源量(avaliable )>=程序執行所需的資源數的程序(need),再假設這個程序安全校驗是成功的,當這個程序執行完畢後,釋放資源後,現在系統當前剩餘的資源(avaliable)=avaliable+該執行緒之前已分配的資源(allocation) ,將該節點程序設為處理時忽略程序,再以上條件為前提進行安全校驗。
安全校驗:一個程序獲得資源後,執行完畢,釋放之前分配的資源,其他的執行緒可以繼續執行,而不會造成死鎖。
這樣就會產生回溯。
滿足條件:是否存在一個程序執行所需的資源數<=當前系統剩餘的資源數。
查詢操作:先判斷回溯的步長(層數)是否等於節點的個數,如果等於說明已經找到了正確路徑,返回真給上一層,如果不滿足,則看一下此層是否存在滿足條件的節點,如果存在,這一該節點為回溯點開始查詢操作。如果都不存在,說明上一層的回溯點不是我們要找的節點,返回假給上一層,並回溯回到上一層節點,將忽略標記清楚,換另一個滿足條件的節點繼續在進行查詢操作。
先以一個滿足條件的節點進行忽略標記(下一次查詢時可忽略此節點),回溯的步長加一,再進行查詢操作(下一層)。
import java.util.Arrays; public class BanksTest { // 用於儲存預操作後的資源變化 static int[] new_Avaliable = null; // 用於儲存預操作的完成度 static boolean[] new_finish = null; // 用於儲存最終的程序執行順序,初始化為非法程序-1 static int right[] = { -1,-1,-1 }; public static void main(String[] args) { // 最大需求量 int[][] max = { { 7,5,3 },{ 3,2,2 },{ 9,{ 2,{ 4,3,3 } }; // 當前系統可用資源量 int[] avaliable = { 3,2 }; // 每個程序執行還需資源量 int[][] need = new int[5][3]; // 每個程序已分配的資源量 int[][] allocation = { { 0,1,0 },1 },{ 0,2 } }; // 用於第一深度預判的初始化 boolean finish[] = { false,false,false }; // 獲取每個程序執行時還需的資源量 for (int i = 0; i < max.length; i++) { for (int j = 0; j < max[i].length; j++) { need[i][j] = max[i][j] - allocation [i][j]; } } // 建立遞迴深度 int deep = 0; // 呼叫回溯遞迴演算法 deepCheck(avaliable,allocation,need,finish,deep,right); int i = 0; // 檢視最終的安全序列的值,看是否存在初始的非法程序,如果存在,則說明該案例不存在安全的程序執行順序 for (; i < right.length; i++) { if (right[i] == -1) { break; } } if (i < right.length) { System.out.println("該案例不存在安全的程序執行順序"); return; } // 列印安全的執行順序 for (int j = 0; j < right.length; j++) { System.out.println(right[j]); } } // 完全遞歸回溯查詢安全順序 public static boolean deepCheck(int[] avaliable,int[][] allocation,int[][] need,boolean finish[],int deep,int right[]) { int j = 0; boolean flog = false; // 如果深度為程序的個數數說明已經查詢到頭了,說明上一深度的程序是安全節點。因為上一深度的程序滿足了當前資源數大於或等於該程序執行所需的資源數,且為安全序列中最後一個節點。 if (deep == need.length) { return true; } // 遍歷所有節點程序開始查詢,直到找到安全校驗成功的的節點程序 for (int i = 0; i < need.length; i++) { // 對於未被標記的進行校驗,已被標記的為已被列為安全節點所以無需再進行校驗 if (!finish[i]) { // 判斷當前的節點程序的剩餘的資源量,是否滿足執行所需的資源量 for (j = 0; j < avaliable.length; j++) { // 不滿足 if (need[i][j] > avaliable[j]) { break; } } // 不滿足則處理下一個節點程序 if (j < avaliable.length) { continue; } else { // 滿足情況 // 複製會被修改的前提條件,已便於當前程序校驗不成功時,可以恢復前提條件,開始下一個節點程序的校驗 new_Avaliable = Arrays.copyOf(avaliable,avaliable.length); new_finish = Arrays.copyOf(finish,finish.length); // 假設當前節點程序是可以校驗成功的節點程序,修改該程序執行完畢後釋放之前分配的程序。 for (j = 0; j < new_Avaliable.length; j++) { new_Avaliable[j] += allocation[i][j]; } // 假設標記當前為校驗成功的安全節點程序,下一深度查詢時會忽略此程序。 new_finish[i] = true; // 增加深度 deep++; // 以上假設為前提,進行下一深度的安全校驗判斷其他所剩餘程序是否可以繼續執行,而不造成死鎖。 flog = deepCheck(new_Avaliable,new_finish,right); // 如果進行安全校驗後為真,說明當前程序是我們要找的程序 if (flog) { // 儲存到最終程序執行序列的陣列中 right[--deep] = i; break; } } } } // 安全校驗成功 if (flog) { return true; } else { // 安全校驗失敗 // 清楚之前的假設標記 new_finish[right[--deep]] = false; return false; } } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。