银行家算法

银行家算法

锁定
本词条由 “科普中国”百科科学词条编写与应用工作项目审核。
银行家算法(Banker's Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。 [1]  
中文名
银行家算法
外文名
Banker's Algorithm
发明者
艾兹格·迪杰斯特拉

目录

  1. 1背景简介
  2. 2安全状态
  3. 3不安全状态
  1. 4数据结构
  2. 5算法原理
  3. 6算法实现
  1. 初始化
  2. 银行家算法
  3. 安全性检查算法

背景简介

在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。
银行家算法是一种最有代表性的避免 死锁的算法。在避免 死锁方法中允许进程动态地申请资源,但系
银行家算法_第1张图片 银行家算法
统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干 数据结构。
要解释银行家算法,必须先解释 操作系统 安全状态和不安全状态。
安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。

安全状态

如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有 死锁发生。

不安全状态

不存在一个安全序列。不安全状态不一定导致 死锁。

数据结构

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]

算法原理

我们可以把 操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金.
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程本次申请的资源数是否超过了该资源所剩余的总量。若超过则拒绝分配资源,若能满足则按当前的申请量分配资源,否则也要推迟分配。

算法实现

初始化

由用户输入数据,分别对可利用资源向量 矩阵AVAILABLE、最大需求矩阵MAX、分配矩阵ALLOCATION、需求矩阵NEED赋值。

银行家算法

在避免 死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生 死锁。
银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免 死锁的算法。
设进程cusneed提出请求REQUEST [i],则银行家算法按如下规则进行判断。
(1)如果REQUEST [cusneed] [i]<= NEED[cusneed][i],则转(2);否则,出错。
(2)如果REQUEST [cusneed] [i]<= AVAILABLE[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=Work+ALLOCATION;
Finish=true;
GOTO 2
(4)如所有的进程Finish= true,则表示安全;否则系统不安全。
银行家算法流程图
银行家算法_第2张图片
算法(C语言实现)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include<STRING.H>
#include<stdio.h>
#include<stdlib.h>
#include<CONIO.H>/*用到了getch()*/
#defineM5/*进程数*/
#defineN3/*资源数*/
#defineFALSE0
#defineTRUE1
/*M个进程对N类资源最大资源需求量*/
intMAX[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};
/*系统可用资源数*/
intAVAILABLE[N]={10,5,7};
/*M个进程已分配到的N类数量*/
intALLOCATION[M][N]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
/*M个进程已经得到N类资源的资源量*/
intNEED[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};
/*M个进程还需要N类资源的资源量*/
intRequest[N]={0,0,0};
voidmain()
{
inti=0,j=0;
charflag;
voidshowdata();
voidchangdata( int );
voidrstordata( int );
intchkerr();
showdata();
enter:
{
printf ( "请输入需申请资源的进程号(从0到" );
printf ( "%d" ,M-1);
printf ( "):" );
scanf ( "%d" ,&i);
}
if (i<0||i>=M)
{
printf ( "输入的进程号不存在,重新输入!\n" );
gotoenter;
}
err:
{
printf ( "请输入进程" );
printf ( "%d" ,i);
printf ( "申请的资源数\n" );
printf ( "类别:ABC\n" );
printf ( "" );
for (j=0;j<N;j++)
{
scanf ( "%d" ,&Request[j]);
if (Request[j]>NEED[i][j])
{
printf ( "%d" ,i);
printf ( "号进程" );
printf ( "申请的资源数>进程" );
printf ( "%d" ,i);
printf ( "还需要" );
printf ( "%d" ,j);
printf ( "类资源的资源量!申请不合理,出错!请重新选择!\n" );
gotoerr;
}
else
{
if (Request[j]>AVAILABLE[j])
{
printf ( "进程" );
printf ( "%d" ,i);
printf ( "申请的资源数大于系统可用" );
printf ( "%d" ,j);
printf ( "类资源的资源量!申请不合理,出错!请重新选择!\n" );
gotoerr;
}
}
}
}
changdata(i);
if (chkerr())
{
rstordata(i);
showdata();
}
else
showdata();
printf ( "\n" );
printf ( "按'y'或'Y'键继续,否则退出\n" );
flag=getch();
if (flag== 'y' ||flag== 'Y' )
{
gotoenter;
}
else
{
exit (0);
}
}
/*显示数组*/
voidshowdata()
{
inti,j;
printf ( "系统可用资源向量:\n" );
printf ( "***Available***\n" );
printf ( "资源类别:ABC\n" );
printf ( "资源数目:" );
for (j=0;j<N;j++)
{
printf ( "%d" ,AVAILABLE[j]);
}
printf ( "\n" );
printf ( "\n" );
printf ( "各进程还需要的资源量:\n" );
printf ( "******Need******\n" );
printf ( "资源类别:ABC\n" );
for (i=0;i<M;i++)
{
printf ( "" );
printf ( "%d" ,i);
printf ( "号进程:" );
for (j=0;j<N;j++)
{
printf ( "%d" ,NEED[i][j]);
}
printf ( "\n" );
}
printf ( "\n" );
printf ( "各进程已经得到的资源量:\n" );
printf ( "***Allocation***\n" );
printf ( "资源类别:ABC\n" );
for (i=0;i<M;i++)
{
printf ( "" );
printf ( "%d" ,i);
printf ( "号进程:" );
/*printf(":\n");*/
for (j=0;j<N;j++)
{
printf ( "%d" ,ALLOCATION[i][j]);
}
printf ( "\n" );
}
printf ( "\n" );
}
/*系统对进程请求响应,资源向量改变*/
voidchangdata(intk)
{
intj;
for (j=0;j<N;j++)
{
AVAILABLE[j]=AVAILABLE[j]-Request[j];
ALLOCATION[k][j]=ALLOCATION[k][j]+Request[j];
NEED[k][j]=NEED[k][j]-Request[j];
}
}
/*资源向量改变*/
voidrstordata(intk)
{
intj;
for (j=0;j<N;j++)
{
AVAILABLE[j]=AVAILABLE[j]+Request[j];
ALLOCATION[k][j]=ALLOCATION[k][j]-Request[j];
NEED[k][j]=NEED[k][j]+Request[j];
}
}
/*安全性检查函数*/
intchkerr() //在假定分配资源的情况下检查系统的安全性
{
intWORK[N],FINISH[M],temp[M]; //temp[]用来记录进程安全执行的顺序
inti,j,m,k=0,count;
for (i=0;i<M;i++)
FINISH[i]=FALSE;
for (j=0;j<N;j++)
WORK[j]=AVAILABLE[j]; //把可利用资源数赋给WORK[]
for (i=0;i<M;i++)
{
count=0;
for (j=0;j<N;j++)
if (FINISH[i]==FALSE&&NEED[i][j]<=WORK[j])
count++;
if (count==N) //当进程各类资源都满足NEED<=WORK时
{
for (m=0;m<N;m++)
WORK[m]=WORK[m]+ALLOCATION[i][m];
FINISH[i]=TRUE;
temp[k]=i; //记录下满足条件的进程
k++;
i=-1;
}
}
for (i=0;i<M;i++)
if (FINISH[i]==FALSE)
{
printf ( "系统不安全!!!本次资源申请不成功!!!\n" );
return1;
}
printf ( "\n" );
printf ( "经安全性检查,系统安全,本次分配成功。\n" );
printf ( "\n" );
printf ( "本次安全序列:" );
for (i=0;i<M;i++) //打印安全系统的进程调用顺序
{
printf ( "进程" );
printf ( "%d" ,temp[i]);
if (i<M-1)
printf ( "->" );
}
printf ( "\n" );
return0;
}
参考资料
  • 1.  《操作系统概念(Operating System Concepts)》

你可能感兴趣的:(银行家算法)