银行家算法实例

银行家算法学习笔记

银行家算法学习笔记


死锁避免——银行家算法的应用背景

要想说银行家,首先得说死锁问题,因为银行家算法就是为了死锁避免提出的。那么,什么是死锁?简单的举个例子:俩人吃饺子,一个人手里拿着酱油,一个人手里拿着醋,拿酱油的对拿着醋的人说:“你把醋给我,我就把酱油给你”;拿醋的对拿着酱油的人说:“不,你把酱油给我,我把醋给你。”

于是,俩人这两份调料是永远吃不上了。这就是死锁。

那么,为啥这个算法叫银行家算法?因为这个算法同样可以用于银行的贷款业务。让我们考虑下面的情况。

一个银行家共有20亿财产
第一个开发商:已贷款15亿,资金紧张还需3亿。
第二个开发商:已贷款5亿,运转良好能收回。
第三个开发商:欲贷款18亿

在这种情况下,如果你是银行家,你怎么处理这种情况?一个常规的想法就是先等着第二个开发商把钱收回来,然后手里有了5个亿,再把3个亿贷款给第一个开发商,等第一个开发商收回来18个亿,然后再把钱贷款给第三个开发商。
这里面什么值得学习呢?最重要的就是眼光放长一点,不要只看着手里有多少钱,同时要注意到别人欠自己的钱怎么能收回来。

那么正经点说这个问题,第一个例子中:醋和酱油是资源,这俩吃饺子的是进程;第二个例子中:银行家是资源,开发商是进程。在操作系统中,有内存,硬盘等等资源被众多进程渴求着,那么这些资源怎么分配给他们才能避免“银行家破产”的风险?


银行家算法

安全序列

安全序列是指对当前申请资源的进程排出一个序列,保证按照这个序列分配资源完成进程,不会发生“酱油和醋”的尴尬问题。

我们假设有进程P1,P2,.....Pn
则安全序列要求满足:Pi(1<=i<=n)需要资源<=剩余资源 + 分配给Pj(1 <= j < i)资源
为什么等号右边还有已经被分配出去的资源?想想银行家那个问题,分配出去的资源就好比第二个开发商,人家能还回来钱,咱得把这个考虑在内。

我们定义下面的数据结构

int n,m; //系统中进程总数n和资源种类总数m
int Available[1..m]; //资源当前可用总量
int Allocation[1..n,1..m]; //当前给分配给每个进程的各种资源数量
int Need[1..n,1..m];//当前每个进程还需分配的各种资源数量
int Work[1..m]; //当前可分配的资源
bool Finish[1..n]; //进程是否结束

安全判定算法

1.初始化

Work = Available(动态记录当前剩余资源)
Finish[i] = false(设定所有进程均未完成)

2.查找可执行进程Pi(未完成但目前剩余资源可满足其需要,这样的进程是能够完成的)

Finish[i] = false          
Need[i] <= Work 
如果没有这样的进程Pi,则跳转到第4步

3.(若有则)Pi一定能完成,并归还其占用的资源,即:

Finish[i] = true           
Work = Work +Allocation[i]
GOTO 第2步,继续查找

4.如果所有进程Pi都是能完成的,即Finish[i]=ture
则系统处于安全状态,否则系统处于不安全状态

伪代码:

Boolean Found;
Work = Available; Finish[1..n] = false; 
while(true){
    //不断的找可执行进程
   Found = false;
   for(i=1; i<=n; i++){
     if(Finish[i]==false && Need[i]<=Work){
        Work = Work + Allocation[i];//把放出去的贷款也当做自己的资产
        Finish[i] = true; 
        Found = true;
      }
    }
   if(Found==false)break;
 }
for(i=1;i<=n;i++) 
  if(Finish[i]==false)return “deadlock”; //如果有进程是完不成的,那么就是有死锁

示例

举个实际例子,假设下面的初始状态:

processAllocationNeedAvailable
 A B CA B CA B C
P00 1 07 4 33 3 2
P12 0 01 2 2 
P23 0 26 0 0 
P32 1 10 1 1 
P40 0 24 3 1 

首先,进入算法第一步,初始化。
那么Work = Available = [3 3 2]

首先看P0:
P0的Need为[7 4 3],Available不能满足,于是跳过去

P1的Need为[1 2 2]可以满足,我们令Work = Allocation[P1] + Work
此时Work = [5 3 2]

再看P2,P2的Need为[6 0 0],那么现有资源不满足。跳过去。

看P3,那么看P3,Work可以满足。那么令Work = Allocation[P3] + Work,此时Work = [7 4 3]

再看P4,Work可以满足。令Work = Allocation[P4] + Work ,此时Work = [7 4 5]

到此第一轮循环完毕,由于找到了可用进程,那么进入第二轮循环。

看P0,Work此时可以满足。令Work = Allocation[P0] + Work ,此时Work = [7 5 5]

再看P2,此时Work可以满足P2。令Work = Allocation[P2] + Work , 此时Work = [10 5 7]

至此,算法运行完毕。找到安全序列<P1,P3,P4,P0,P2>,证明此时没有死锁危险。(安全序列未必唯一)


资源请求算法

之前说完了怎么判定当前情况是否安全,下面就是说当有进程新申请资源的时候如何处理。
我们将第i个进程请求的资源数记为Requests[i]

算法流程:

1.如果Requests[i]<=Need[i],则转到第二步。否则,返回异常。这一步是控制进程申请的资源不得大于需要的资源

2.如果Requests[i]<=Available,则转到第三步,否则Pi等待资源。

3.如果满足前两步,那么做如下操作:

Available = Available -Requests[i]
Allocation = Allocation[i]+Requests[i]
Need[i]=Need[i]-Requests[i]
调用安全判定算法,检查是否安全
if(安全)
{
    申请成功,资源分配
}
else
{
    申请失败,资源撤回。第三步前几个操作进行逆操作
}

 

参考文献:

https://www.cnblogs.com/chuxiuhong/p/6103928.html

 

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的银行家算法的实现示例,使用 C 语言编写: ```c #include <stdio.h> #include <stdbool.h> #define NUM_RESOURCES 3 #define NUM_PROCESSES 5 int available[NUM_RESOURCES] = {3, 3, 2}; int max_need[NUM_PROCESSES][NUM_RESOURCES] = { {7, 5, 3}, {3, 2, 2}, {9, 0, 2}, {2, 2, 2}, {4, 3, 3}, }; int allocated[NUM_PROCESSES][NUM_RESOURCES] = { {0, 1, 0}, {2, 0, 0}, {3, 0, 2}, {2, 1, 1}, {0, 0, 2}, }; // 计算已分配资源和需要资源 void calculate_need(int need[NUM_PROCESSES][NUM_RESOURCES], int allocated[NUM_PROCESSES][NUM_RESOURCES], int max_need[NUM_PROCESSES][NUM_RESOURCES]) { for (int i = 0; i < NUM_PROCESSES; i++) { for (int j = 0; j < NUM_RESOURCES; j++) { need[i][j] = max_need[i][j] - allocated[i][j]; } } } // 判断一个进程是否需要的资源是否小于等于可用资源 bool check_process(int process, int need[NUM_PROCESSES][NUM_RESOURCES], int available[NUM_RESOURCES]) { for (int i = 0; i < NUM_RESOURCES; i++) { if (need[process][i] > available[i]) { return false; } } return true; } // 判断当前状态是否安全 bool check_safe(int available[NUM_RESOURCES], int allocated[NUM_PROCESSES][NUM_RESOURCES], int max_need[NUM_PROCESSES][NUM_RESOURCES]) { int need[NUM_PROCESSES][NUM_RESOURCES]; calculate_need(need, allocated, max_need); bool finish[NUM_PROCESSES] = {false}; int work[NUM_RESOURCES]; for (int i = 0; i < NUM_RESOURCES; i++) { work[i] = available[i]; } int safe_seq[NUM_PROCESSES]; int count = 0; while (count < NUM_PROCESSES) { bool found = false; for (int i = 0; i < NUM_PROCESSES; i++) { if (!finish[i] && check_process(i, need, work)) { finish[i] = true; for (int j = 0; j < NUM_RESOURCES; j++) { work[j] += allocated[i][j]; } safe_seq[count] = i; count++; found = true; } } if (!found) { return false; } } return true; } // 请求资源 bool request_resources(int process, int request[NUM_RESOURCES], int available[NUM_RESOURCES], int allocated[NUM_PROCESSES][NUM_RESOURCES], int max_need[NUM_PROCESSES][NUM_RESOURCES]) { int need[NUM_PROCESSES][NUM_RESOURCES]; calculate_need(need, allocated, max_need); for (int i = 0; i < NUM_RESOURCES; i++) { if (request[i] > need[process][i]) { return false; } if (request[i] > available[i]) { return false; } } for (int i = 0; i < NUM_RESOURCES; i++) { available[i] -= request[i]; allocated[process][i] += request[i]; need[process][i] -= request[i]; } if (!check_safe(available, allocated, max_need)) { for (int i = 0; i < NUM_RESOURCES; i++) { available[i] += request[i]; allocated[process][i] -= request[i]; need[process][i] += request[i]; } return false; } return true; } // 打印状态 void print_status() { printf("可用资源:"); for (int i = 0; i < NUM_RESOURCES; i++) { printf(" %d", available[i]); } printf("\n最大需求:\n"); for (int i = 0; i < NUM_PROCESSES; i++) { printf("进程 %d:", i); for (int j = 0; j < NUM_RESOURCES; j++) { printf(" %d", max_need[i][j]); } printf("\n"); } printf("已分配资源:\n"); for (int i = 0; i < NUM_PROCESSES; i++) { printf("进程 %d:", i); for (int j = 0; j < NUM_RESOURCES; j++) { printf(" %d", allocated[i][j]); } printf("\n"); } } // 测试代码 int main() { print_status(); if (check_safe(available, allocated, max_need)) { printf("当前状态安全\n"); } else { printf("当前状态不安全\n"); } int request[NUM_RESOURCES] = {1, 0, 2}; if (request_resources(1, request, available, allocated, max_need)) { printf("请求资源成功\n"); print_status(); } else { printf("请求资源失败\n"); } return 0; } ``` 运行上述代码,将输出以下结果: ``` 可用资源: 3 3 2 最大需求: 进程 0: 7 5 3 进程 1: 3 2 2 进程 2: 9 0 2 进程 3: 2 2 2 进程 4: 4 3 3 已分配资源: 进程 0: 0 1 0 进程 1: 2 0 0 进程 2: 3 0 2 进程 3: 2 1 1 进程 4: 0 0 2 当前状态安全 请求资源成功 可用资源: 2 3 0 最大需求: 进程 0: 7 5 3 进程 1: 3 2 2 进程 2: 9 0 2 进程 3: 2 2 2 进程 4: 4 3 3 已分配资源: 进程 0: 0 1 0 进程 1: 3 0 2 进程 2: 3 0 2 进程 3: 2 1 1 进程 4: 0 0 2 ``` 可以看到,初始状态下当前状态是安全的,请求资源成功后仍然是安全状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值