银行家算法学习笔记

时间:2021-01-02 10:24:14

银行家算法是经典的死锁避免算法,由两个部分构成。

所需要的数据结构:(n是系统中的进程数量,m是资源类型的数量)

Available:长度为m的向量,表示当前系统各资源的可用数量。Available[j]==k,表示类型为j的资源 ,可用数量为k。

Max:nxm的矩阵,表示所有进程对资源的最大需求量。Max[i][j]==k,表示进程Pi对类型为j的资源的最大需求量为k。

Allocation:nxm的矩阵,表示当前时刻,进程所占有的资源情况。Allocation[i][j]==k,表示进程Pi当前占有k个j类型的资源。

Need:nxm的矩阵,表示进程对资源的申请情况。Need[i][j]==k,表示进程Pi还需要k的j类型的资源才能完成它的工作。注意,

Need[i][j]=Max[i][j]-Allocation[i][j]。

我们可以将Need,Max,Allocation这些二维数组的每一行看作是一个向量,Need[i]表示进程Pi还需要申请的资源数量,Max[i]表示Pi对资源的最大需求数量。

一、安全算法

1. 创建向量Work和Finish,长度分别为m和n。初始化Work=Available,Finish[i]=false, for i = 0,1,...,n-1

2. 在进程集合P中寻找一个满足以下两个条件的i:

  1) Finish[i] == false

  2) Need[i] <= Work(Need[i]的每一个分量都小于等于Work的每一个分量)

    如果没有这样的i存在或者集合P为空,跳到步骤4

3. Work = Work + Allocation[i];

    Finish[i] = true;

    P - {Pi};

4. 如果对于所有i,Finish[i] == true,则系统是安全的,否则是不安全的。

C++代码:

银行家算法学习笔记银行家算法学习笔记
 1 #include <stdio.h>
 2 #define M 3
 3 #define N 5
 4 int Available[M] = {3,3,2};
 5 int Max[N][M] = {
 6     {7,5,3},
 7     {3,2,2},
 8     {9,0,2},
 9     {2,2,2},
10     {4,3,3}
11 };
12 int Allocation[N][M] = {
13     {0,1,0},
14     {2,0,0},
15     {3,0,2},
16     {2,1,1},
17     {0,0,2}
18 };
19 
20 int Need[N][M];
21 
22 void initNeed() {
23     int i, j;
24     for (i = 0; i < N; i++) {
25         for (j = 0; j < M; j++) {
26             Need[i][j] = Max[i][j] - Allocation[i][j];
27         }
28     }
29 }
30 
31 bool isLessAndEqual(int Need[], int Work[]) {
32     int result = 0;
33     for (int j = 0; j < M; j++) {
34         if (Need[j] > Work[j])
35             return false;
36     }
37     return true;
38 }
39 
40 void addTo(int to[], int from[]) {
41     for (int i = 0; i < M; i++) {
42         to[i] += from[i];
43     }
44 }
45 
46 // 判断当前系统是否处于安全状态,看能否找出一个安全序列
47 bool isSafe() {
48     int Work[M];
49     bool Finish[N] = {false};
50     for (int i = 0; i < M; i++) {
51         Work[i] = Available[i];
52     }
53     printf("正在判断系统是否安全:\n");
54     int counter = N;
55     bool found;    // 标记遍历一次是否有找到可以分配的进程,如果没有则退出循环,不需再继续遍历
56     while (counter > 0) {
57         found = false;
58         for (int i = 0; i < N; i++) {
59             if (!Finish[i] && isLessAndEqual(Need[i], Work)) {
60                 addTo(Work, Allocation[i]);
61                 Finish[i] = true;
62                 counter--;
63                 printf("%d ", i);
64                 found = true;
65             }
66         }
67         if (found == false)
68             break;
69     }
70     printf("\n");
71     for (int i = 0; i < N; i++)     {
72         if (!Finish[i])
73             return false;
74     }
75 
76     return true;
77 }
78 
79 int main()
80 {
81     initNeed();
82     if (isSafe()) {
83         printf("安全!\n");
84     } else {
85         printf("不安全!\n");
86     }
87 
88 }
View Code

 二、资源分配算法

令Request[i]表示进程Pi的请求向量,Request[i][j] == k表示Pi请求k个类型为j的资源,当进程申请资源时执行以下步骤:

1. 如果Request[i] <= Need[i],跳到步骤2,否则抛出错误,因为Pi的请求数量已经超过了它的最大资源需求数。

2. 如果Request[i] <= Available,跳到步骤3,否则Pi进入等待状态,因为没有足够多的资源。

3. 假定系统可以分配给进程Pi所请求的资源,并按以下方式修改状态:

  Available = Available - Request[i];

  Allocation[i] = Allocation[i] + Request[i];

  Need[i] = Need[i] - Request[i];

   此时判断系统是否处于安全状态,如果是则事务结束,进程Pi可以分配到所需要的资源。否则Pi必须等待,且各数据结构恢复到之前的状态。