试验完成时间:2020.5.26
银行家算法:
把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
操作系统按照银行家制定的规则设计的银行家算法为:
(1)进程首次申请资源的分配:如果系统现存资源可以满足该进程的最大需求量,则按当前的申请量分配资源,否则推迟分配。
(2)进程在执行中继续申请资源的分配:若该进程已占用的资源与本次申请的资源之和不超过对资源的最大需求量,且现存资源能满足该进程尚需的最大资源量,则按当前申请量分配资源,否则推迟分配。
(3)至少一个进程能完成:在任何时刻保证至少有一个进程能得到所需的全部资源而执行到结束。
银行家算法通过动态地检测系统中资源分配情况和进程对资源的需求情况来决定如何分配资源,并能在确保系统处于安全状态时才把资源分配给申请者,从而避免系统发生死锁。
# 具 体 思 路 该 博 客 讲 的 很 详 细 #
参考代码设计
1、系统有资源r1:100,r2:100,r3:100,r4:100
2、生成进程
begin
repeat:
sleep(随机数0)
//资源数量5,3,0,20是随机数
进程请求资源:r1:5,r2:3,r3:0,r4:20
//请求与获得的资源皆为该进程需求资源的MAX
进程获得资源
sleep(随机数1)
进程释放资源 r1
sleep(随机数2)
进程释放资源 r2
sleep(随机数3)
进程释放资源 r3
sleep(随机数4)
进程释放资源 r4
随机决定是:
1)结束进程还是
2)跳转 repeat
end
一共四种系统资源,每种初始数量100
线程数量,每个进程对四种资源的最大需求,各个时间段线程请求资源数 使用随机数生成。
代码实现:
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include <pthread.h>
#include <unistd.h>
#include <windows.h>
#define ull unsigned long long
#define ll long long
#define inf 2100000000
#define endl '\n'
#define pii pair<long long,long long>
#define eps 1e-6
using namespace std;
const double pi=3.14159265358;
const int maxn=15;
const int mod=998244353;
int avable[maxn]={100,100,100,100}; // 可用资源
int mx[maxn][maxn]; // 最大需求
int used[maxn][maxn]; // 已用资源
int need[maxn][maxn]; // 还需要的资源
int work[maxn]; // 目前可用资源
bool finish[maxn]; // 当前进程是否完成
int n=4,m,x; // 系统资源种类数,总进程数,进程号
int restm; // 剩余执行线程数
int zyzs[maxn]={100,100,100,100}; // 系统资源总数
int vis[15]; // 标记访问
pthread_mutex_t mtx;// 互斥信号量
pthread_cond_t cd;// 条件变量
// 安全性检查
int safecheck(int id) {
int cmt[15]; // 线程安全顺序
int favable[maxn]; // 用一个镜像数组检测安全
for(int i=0;i<n;i++) {
favable[i]=avable[i];
}
int f=0;
memset(vis,0,sizeof(vis));
while(f<restm) {
// 当目前判断数小于剩下线程数时
bool flag=0;
for(int i=0;i<m;i++) {
if(!finish[i]&&!vis[i]) {
int flag2=0;
for(int j=0;j<n;j++) {
if(need[i][j]>favable[j]) {
flag2=1;
break;
}
}
if(!flag2) { // 若该进程所需资源小于可用资源
flag=1;
vis[i]=1;
cmt[f++]=i;
for(int j=0;j<n;j++) {
favable[j]+=used[i][j];
}
}
}
}
if(!flag) { // 若没有可运行的进程,则停止
break;
}
}
if(f==restm) {
cout<<"系统处于安全状态,以下为安全序列: "<<endl;
for(int i=0;i<f;i++) {
cout<<cmt[i]+1<<" ";
}
cout<<endl<<endl;
return 1;
}
else {
cout<<"此时系统不安全,线程 "<<id+1<<" 将被阻塞!"<<endl;
// 等到下次avable更新再将该进程唤醒
return 0;
}
}
// 判断进程id对资源res的请求
int banker(int id,vector<int>res) {
for(int i=0;i<res.size();i++) {
int k=res[i];
if(k<=need[id][i]) {
// 进程请求资源数大于可用资源数,进程堵塞
if(k>avable[i]) {
cout<<"线程 "<<id+1<<" 请求的 "<<i+1<<" 类资源大于该类资源可用数目!"<<endl;
return 1;
}
}
else {
// 进程申请资源大于系统资源数,重新申请
cout<<"线程 "<<id+1<<" 请求的 "<<i+1<<" 类资源大于该类资源总数!"<<endl;
return 2;
}
}
// 移动资源
for(int i=0;i<res.size();i++) {
int k=res[i];
avable[i]-=k;
used[id][i]+=k;
need[id][i]-=k;
}
// 检测安全,若无法分配,则先阻塞
if(!safecheck(id)) {
for(int i=0;i<res.size();i++) {
int k=res[i];
avable[i]+=k;
used[id][i]-=k;
need[id][i]+=k;
}
return 3;
}
cout<<"线程 "<<id+1<<" 获得资源: "<<endl<<" | ";
for(int i=0;i<res.size();i++) {
cout<<"第 "<<i+1<<" 类: "<<res[i]<<" | ";
}
cout<<endl<<endl;
return 0;
}
void init() {
cout<<"系统资源种类总数: " <<n<<endl;
cout<<n<<" 种资源总数: "<<endl;
for(int i=0;i<n;i++) {
cout<<avable[i]<<" ";
}
cout<<endl<<endl;
m=rand()%6+5;
restm=m;
cout<<"进程数: "<<m<<endl;
cout<<m<<" 行 "<<n<<" 列代表 "<<m<<" 个进程对 "<<n<<" 种资源的最大需求: "<<endl;
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++) {
mx[i][j]=rand()%101;
need[i][j]=mx[i][j];
cout<<mx[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
void *thyx(void *arg) {
int id=(int) arg;
// 随机请求资源
vector<int>res;
for(int i=0;i<n;i++) {
if(need[id][i]==0) {
res.push_back(0);
}
else {
res.push_back(rand()%(need[id][i]+1));
}
}
bool isfinish=0; // flag
while(1) {
pthread_mutex_lock(&mtx); // 加锁
isfinish=0;
// 判断该线程是否已经完成资源分配
for(int i=0;i<n;i++) {
if(need[id][i]!=0) {
isfinish=1;
break;
}
}
// 资源完成分配
if(!isfinish) {
cout<<"线程 "<<id+1<<" 完成分配,程序继续执行"<<endl;
Sleep(rand()%101);
cout<<"线程 "<<id+1<<" 执行完毕"<<endl<<endl;
restm--;
finish[id]=1; // 该线程执行完成
// 资源回收
for(int i=0;i<n;i++) {
avable[i]+=used[id][i];
cout<<"线程 "<<id+1<<" 释放资源 "<<i+1<<endl;
Sleep(rand()%101);
used[id][i]=0;
}
pthread_cond_broadcast(&cd); // 唤醒所有在cd,mtx中wait的线程
pthread_mutex_unlock(&mtx); // 解锁
pthread_exit(NULL); // 退出该线程
}
int chk=banker(id,res);
if(chk==1||chk==3) {
// 系统不安全,或者所需资源大于系统资源,则先线程阻塞
pthread_cond_wait(&cd, &mtx);
}
else if(chk==0||chk==2) {
// 分配成功,或者得重新分配
res.clear();
for(int i=0;i<n;i++) {
if(need[id][i]==0) {
res.push_back(0);
}
else {
res.push_back(rand()%(need[id][i]+1));
}
}
}
Sleep(rand()%101);
pthread_mutex_unlock(&mtx); // 解锁
}
}
int main() {
//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
srand(time(NULL));
pthread_t td[maxn]; // 线程
pthread_mutex_init(&mtx,NULL); // 互斥锁初始化
pthread_cond_init(&cd, NULL); // 条件变量初始化
init();
for(int i=0;i<m;i++) {
pthread_create(&td[i],NULL,thyx,(void*)i); // 创建线程
}
for(int i=0;i<m;i++) {
pthread_join(td[i],NULL); // 调用时阻塞当前线程直到返回
}
cout<<endl<<" *********************** "<<endl<<endl;
cout<<"至此,所有线程执行完毕!!!"<<endl;
return 0;
}
部分实现图:
试验完成时间:2020.5.26
银行家算法:
把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
为保证资金的安全,银行家规定:
(1) 当一个顾客对资金的最大需求量不超过银行家现有的资金时就可接纳该顾客;
(2) 顾客可以分期贷款,但贷款的总数不能超过最大需求量;
(3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款;
(4) 当顾客得到所需的全部资金后,一定能在有限的时间里归还所有的资金。
操作系统按照银行家制定的规则设计的银行家算法为:
(1)进程首次申请资源的分配:如果系统现存资源可以满足该进程的最大需求量,则按当前的申请量分配资源,否则推迟分配。
(2)进程在执行中继续申请资源的分配:若该进程已占用的资源与本次申请的资源之和不超过对资源的最大需求量,且现存资源能满足该进程尚需的最大资源量,则按当前申请量分配资源,否则推迟分配。
(3)至少一个进程能完成:在任何时刻保证至少有一个进程能得到所需的全部资源而执行到结束。
银行家算法通过动态地检测系统中资源分配情况和进程对资源的需求情况来决定如何分配资源,并能在确保系统处于安全状态时才把资源分配给申请者,从而避免系统发生死锁。
# 具 体 思 路 该 博 客 讲 的 很 详 细 #
参考代码设计
1、系统有资源r1:100,r2:100,r3:100,r4:100
2、生成进程
begin
repeat:
sleep(随机数0)
//资源数量5,3,0,20是随机数
进程请求资源:r1:5,r2:3,r3:0,r4:20
//请求与获得的资源皆为该进程需求资源的MAX
进程获得资源
sleep(随机数1)
进程释放资源 r1
sleep(随机数2)
进程释放资源 r2
sleep(随机数3)
进程释放资源 r3
sleep(随机数4)
进程释放资源 r4
随机决定是:
1)结束进程还是
2)跳转 repeat
end
一共四种系统资源,每种初始数量100
线程数量,每个进程对四种资源的最大需求,各个时间段线程请求资源数 使用随机数生成。
代码实现:
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include <pthread.h>
#include <unistd.h>
#include <windows.h>
#define ull unsigned long long
#define ll long long
#define inf 2100000000
#define endl '\n'
#define pii pair<long long,long long>
#define eps 1e-6
using namespace std;
const double pi=3.14159265358;
const int maxn=15;
const int mod=998244353;
int avable[maxn]={100,100,100,100}; // 可用资源
int mx[maxn][maxn]; // 最大需求
int used[maxn][maxn]; // 已用资源
int need[maxn][maxn]; // 还需要的资源
int work[maxn]; // 目前可用资源
bool finish[maxn]; // 当前进程是否完成
int n=4,m,x; // 系统资源种类数,总进程数,进程号
int restm; // 剩余执行线程数
int zyzs[maxn]={100,100,100,100}; // 系统资源总数
int vis[15]; // 标记访问
pthread_mutex_t mtx;// 互斥信号量
pthread_cond_t cd;// 条件变量
// 安全性检查
int safecheck(int id) {
int cmt[15]; // 线程安全顺序
int favable[maxn]; // 用一个镜像数组检测安全
for(int i=0;i<n;i++) {
favable[i]=avable[i];
}
int f=0;
memset(vis,0,sizeof(vis));
while(f<restm) {
// 当目前判断数小于剩下线程数时
bool flag=0;
for(int i=0;i<m;i++) {
if(!finish[i]&&!vis[i]) {
int flag2=0;
for(int j=0;j<n;j++) {
if(need[i][j]>favable[j]) {
flag2=1;
break;
}
}
if(!flag2) { // 若该进程所需资源小于可用资源
flag=1;
vis[i]=1;
cmt[f++]=i;
for(int j=0;j<n;j++) {
favable[j]+=used[i][j];
}
}
}
}
if(!flag) { // 若没有可运行的进程,则停止
break;
}
}
if(f==restm) {
cout<<"系统处于安全状态,以下为安全序列: "<<endl;
for(int i=0;i<f;i++) {
cout<<cmt[i]+1<<" ";
}
cout<<endl<<endl;
return 1;
}
else {
cout<<"此时系统不安全,线程 "<<id+1<<" 将被阻塞!"<<endl;
// 等到下次avable更新再将该进程唤醒
return 0;
}
}
// 判断进程id对资源res的请求
int banker(int id,vector<int>res) {
for(int i=0;i<res.size();i++) {
int k=res[i];
if(k<=need[id][i]) {
// 进程请求资源数大于可用资源数,进程堵塞
if(k>avable[i]) {
cout<<"线程 "<<id+1<<" 请求的 "<<i+1<<" 类资源大于该类资源可用数目!"<<endl;
return 1;
}
}
else {
// 进程申请资源大于系统资源数,重新申请
cout<<"线程 "<<id+1<<" 请求的 "<<i+1<<" 类资源大于该类资源总数!"<<endl;
return 2;
}
}
// 移动资源
for(int i=0;i<res.size();i++) {
int k=res[i];
avable[i]-=k;
used[id][i]+=k;
need[id][i]-=k;
}
// 检测安全,若无法分配,则先阻塞
if(!safecheck(id)) {
for(int i=0;i<res.size();i++) {
int k=res[i];
avable[i]+=k;
used[id][i]-=k;
need[id][i]+=k;
}
return 3;
}
cout<<"线程 "<<id+1<<" 获得资源: "<<endl<<" | ";
for(int i=0;i<res.size();i++) {
cout<<"第 "<<i+1<<" 类: "<<res[i]<<" | ";
}
cout<<endl<<endl;
return 0;
}
void init() {
cout<<"系统资源种类总数: " <<n<<endl;
cout<<n<<" 种资源总数: "<<endl;
for(int i=0;i<n;i++) {
cout<<avable[i]<<" ";
}
cout<<endl<<endl;
m=rand()%6+5;
restm=m;
cout<<"进程数: "<<m<<endl;
cout<<m<<" 行 "<<n<<" 列代表 "<<m<<" 个进程对 "<<n<<" 种资源的最大需求: "<<endl;
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++) {
mx[i][j]=rand()%101;
need[i][j]=mx[i][j];
cout<<mx[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
void *thyx(void *arg) {
int id=(int) arg;
// 随机请求资源
vector<int>res;
for(int i=0;i<n;i++) {
if(need[id][i]==0) {
res.push_back(0);
}
else {
res.push_back(rand()%(need[id][i]+1));
}
}
bool isfinish=0; // flag
while(1) {
pthread_mutex_lock(&mtx); // 加锁
isfinish=0;
// 判断该线程是否已经完成资源分配
for(int i=0;i<n;i++) {
if(need[id][i]!=0) {
isfinish=1;
break;
}
}
// 资源完成分配
if(!isfinish) {
cout<<"线程 "<<id+1<<" 完成分配,程序继续执行"<<endl;
Sleep(rand()%101);
cout<<"线程 "<<id+1<<" 执行完毕"<<endl<<endl;
restm--;
finish[id]=1; // 该线程执行完成
// 资源回收
for(int i=0;i<n;i++) {
avable[i]+=used[id][i];
cout<<"线程 "<<id+1<<" 释放资源 "<<i+1<<endl;
Sleep(rand()%101);
used[id][i]=0;
}
pthread_cond_broadcast(&cd); // 唤醒所有在cd,mtx中wait的线程
pthread_mutex_unlock(&mtx); // 解锁
pthread_exit(NULL); // 退出该线程
}
int chk=banker(id,res);
if(chk==1||chk==3) {
// 系统不安全,或者所需资源大于系统资源,则先线程阻塞
pthread_cond_wait(&cd, &mtx);
}
else if(chk==0||chk==2) {
// 分配成功,或者得重新分配
res.clear();
for(int i=0;i<n;i++) {
if(need[id][i]==0) {
res.push_back(0);
}
else {
res.push_back(rand()%(need[id][i]+1));
}
}
}
Sleep(rand()%101);
pthread_mutex_unlock(&mtx); // 解锁
}
}
int main() {
//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
srand(time(NULL));
pthread_t td[maxn]; // 线程
pthread_mutex_init(&mtx,NULL); // 互斥锁初始化
pthread_cond_init(&cd, NULL); // 条件变量初始化
init();
for(int i=0;i<m;i++) {
pthread_create(&td[i],NULL,thyx,(void*)i); // 创建线程
}
for(int i=0;i<m;i++) {
pthread_join(td[i],NULL); // 调用时阻塞当前线程直到返回
}
cout<<endl<<" *********************** "<<endl<<endl;
cout<<"至此,所有线程执行完毕!!!"<<endl;
return 0;
}
部分实现图: