实验三 进程的死锁避免算法
一、实验目的
根据银行家算法的思想,编写程序,解决并发进程死锁问题。
二、背景知识
本实验要求设计并实现银行家算法。银行家算法是死锁避免的经典算法,其核心思想是:进程动态地申请资源,每次申请资源时系统都执行安全状态检查算法判断本次申请是否会造成系统处于不安全状态,如果不安全则阻塞进程;如果安全状态,则完成资源分配。
安全状态检查算法的思想是找到一个安全序列,使所有进程都能执行完毕。如果找到,则处于安全状态,否则为不安全状态。
三、实验内容与步骤
进程的死锁避免算法。编写一段程序,模拟银行家算法,解决进程死锁问题。
利用Clion实现上述程序设计和调试操作,根据提示输入相应的资源请求,对于算法操作的成功与否提供一定的提示框。
通过阅读和分析实验程序,熟悉进程的死锁问题。
四、工具/准备工作
在开始本实验前,回顾教科书相关内容
需要做如下准备:
- 一台运行Windows 11操作系统的计算机
- 计算机中安装了Clion
五、实验过程
(一)数据结构
struct state{
int resource[m];
int available[m];
int claim[n][m];
int alloc[n][m];
int need[n][m];
};
state bank;
(二)初始化状态读入:
本次实验以一下数据作为测试数据;
9 3 6
0 1 1
3 2 2
6 1 3
3 1 4
4 2 2
1 0 0
6 1 2
2 1 1
0 0 2
void init_input(){
// cout << "输入进程资源: ";
for(int i = 0; i < m; i++){
cin >> bank.resource[i];
}
// cout << "输入当前可用资源: ";
for(int i = 0; i < m; i++){
cin >> bank.available[i];
}
// cout << "输入进程所需最大资源数: ";
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cin >> bank.claim[i][j];
}
}
// cout << "输入进程已获得最大资源数: ";
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cin >> bank.alloc[i][j];
}
}
//计算need
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
bank.need[i][j] = bank.claim[i][j] - bank.alloc[i][j];
}
}
}
(三)判断是否是安全
boolean safe(){
int Available[m];
//用于临时计算的数组
for(int i = 0; i < m; i++)
Available[i] = bank.available[i];
vector<int> flags;
while(true){
int temp = flags.size();
for(int i = 0; i < n; i++){
if(count(flags.begin(), flags.end(), i) > 0){
continue;
}
boolean flag = true;
for(int j = 0; j < m; j++){
if(bank.need[i][j] <= Available[j]){
continue;
}
else{
flag = false;
break;
}
}
if(flag){
//该进程满足条件
flags.push_back(i);
cout << "释放:" << i + 1<< endl;
for(int j = 0; j < m; j++){
//进程运行完后释放资源
Available[j] += bank.alloc[i][j];
}
}
}
if(flags.size() == temp) {
if(flags.size() == n){
return true;
}
else{
return false;
}
break;
}
}
}
int main(){
init_input();
if(safe()){
cout << "safe\n";
}
else{
cout << "unsafe\n";
}
}
首先使用一个vector数组用于记录已经完成的进程编号,若遍历到的进程已经完成,则跳过,若已有资源满足某进程还需要的资源,则将资源分配给该进程,完成该进程后释放该进程所占有的所有资源,继续下一个进程。
直到全部遍历完之后,vector数组中没有增加编号,说明已经判断出结果,若数组规模等于进程数,说明是安全的状态即所有进程可以正常运行完。
(四)完整源码:
#include <cstdlib>
#include <windows.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int n = 4;//进程数
const int m = 3;//资源数
struct state{
int resource[m];
int available[m];
int claim[n][m];
int alloc[n][m];
int need[n][m];
};
state bank;
void init_input(){
// cout << "输入进程资源: ";
for(int i = 0; i < m; i++){
cin >> bank.resource[i];
}
// cout << "输入当前可用资源: ";
for(int i = 0; i < m; i++){
cin >> bank.available[i];
}
// cout << "输入进程所需最大资源数: ";
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cin >> bank.claim[i][j];
}
}
// cout << "输入进程已获得最大资源数: ";
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cin >> bank.alloc[i][j];
}
}
//计算need
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
bank.need[i][j] = bank.claim[i][j] - bank.alloc[i][j];
}
}
}
boolean safe(){
int Available[m];
for(int i = 0; i < m; i++)
Available[i] = bank.available[i];
vector<int> flags;
while(true){
int temp = flags.size();
for(int i = 0; i < n; i++){
if(count(flags.begin(), flags.end(), i) > 0){
continue;
}
boolean flag = true;
for(int j = 0; j < m; j++){
if(bank.need[i][j] <= Available[j]){
continue;
}
else{
flag = false;
break;
}
}
if(flag){
//该进程满足条件
flags.push_back(i);
cout << "释放:" << i + 1<< endl;
for(int j = 0; j < m; j++){
//进程运行完后释放资源
Available[j] += bank.alloc[i][j];
}
}
}
if(flags.size() == temp) {
if(flags.size() == n){
return true;
}
else{
return false;
}
break;
}
}
}
int main(){
init_input();
if(safe()){
cout << "safe\n";
}
else{
cout << "unsafe\n";
}
}
(五)运行结果
六、实验总结
通过本次银行家算法的实验,通过编程实现银行家算法,更加深刻理解了银行家算法在动态避免死锁时的运行机制。