银行家算法数据结构 
(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]

银行家算法 
  在避免死锁的方法中,所施加的限制条件较弱,有可能获得令人满意的系统性能。在该方法中把系统的状态分为安全状态和不安全状态,只要能使系统始终都处于安全状态,便可以避免发生死锁。 
银行家算法的基本思想是分配资源之前,判断系统是否是安全的;若是,才分配。它是最具有代表性的避免死锁的算法。 
设进程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,则表示安全;否则系统不安全。

#include<iostream>
#include<cstdio>
#include<vector>
#include<ctime>
#include<cstring>
#include<unistd.h>
#include<cstdlib>
#define RESTYPE 100 //资源的种类数
#define NTHREAD 50 //线程的数目
using namespace std; pthread_mutex_t mutex;//互斥信号量
pthread_cond_t cond;//条件变量 class BankerAlgorithm {//银行家算法
public:
int nthread;//线程数
int restThread;//剩余正在执行的线程数目
int nres;//资源数
int vis[NTHREAD];//标示这个进程有没有访问过
int threadFinished[NTHREAD];//标示这个线程是否已经结束
vector<int> resMax[NTHREAD];//每个线程对各类资源的最大的需求量
vector<int> resAllocation[NTHREAD];//每个线程当前应经分配到各类资源的情况
vector<int> resNeed[NTHREAD];//每个线程还需要每类资源的情况
vector<int> resAvailable;//各类资源的剩余可以利用的 private:
void toNeed(){
for(int i=; i<nthread; ++i)
for(int j=; j<nres; ++j)
resNeed[i].push_back(resMax[i][j]), resAllocation[i].push_back();
} bool threadAafetyDetection(int idThread){//线程安全检测
vector<int> tmpResAvailable(resAvailable);
vector<int> threadSafeSequence;//线程安全序列
int cntThread = ;
memset(vis, , sizeof(vis));
while(threadSafeSequence.size() < restThread){
bool findRunThread = false;
for(int i=; i<nthread; ++i)
if(!vis[i] && !threadFinished[i]){
int j;
for(j=; j<nres; ++j)
if(resNeed[i][j] > tmpResAvailable[j])
break;
if(j >= nres){//各类所需要的资源的数目 小于或等于各类剩余资源的数目
//该进程可以成功的运行完毕
findRunThread = true;
vis[i] = ;
threadSafeSequence.push_back(i);
for(j=; j<nres; ++j)
tmpResAvailable[j] += resAllocation[i][j];
}
}
if(!findRunThread) break;//找不到下一个可以运行的线程,则退出
} if(threadSafeSequence.size() == restThread){
cout<<"此时系统处于安全状态,存在线程安全序列如下:"<<endl;
for(int i=; i<threadSafeSequence.size(); ++i)
cout<<threadSafeSequence[i]<<" ";
cout<<endl;
return true;
} else {
cout<<"此时系统处于不安全状态!!!资源无法分配!!!进程"<<idThread<<"将被阻塞!!!"<<endl;//等到下一次resAvailable更新的时候再将该进程唤醒
return false;
}
} public:
BankerAlgorithm(){
} void init(){
memset(threadFinished, , sizeof(threadFinished));
//初始化线程的数目, 资源种类的数目以及每种资源的数目
cout<<"请输入线程的数目和资源的种类数目:"<<endl;
cin>>nthread>>nres;
restThread = nthread;
cout<<"请输入每种资源的数目:" <<endl;
for(int i=; i<nres; ++i){
int k;
cin>>k;
resAvailable.push_back(k);
} cout<<"请输入每个线程对某类资源最大的需求:"<<endl;
for(int i=; i<nthread; ++i){
cout<<"线程"<<i<<"需要的资源:"<<endl;
for(int j=; j<nres; ++j){
int k;
cin>>k;
resMax[i].push_back(k);
}
}
toNeed();
} void returnRes(int idThread){
for(int i=; i<nres; ++i)
resAvailable[i] += resAllocation[idThread][i], resAllocation[idThread][i]=;
} int bankerAlgorithm(int idThread, vector<int>res){//进程idThread对资源idRes的请求数量为k
for(int i=; i<res.size(); ++i){
int idRes=i, k = res[i];
if(k <= resNeed[idThread][idRes]){
if(k > resAvailable[idRes]){
//让进程阻塞
cout<<"ERROR!!!线程"<<idThread<<"请求"<<idRes<<"类资源数目大于该类剩余资源的数目!"<<endl<<endl;
return ;
}
} else {//让进程重新请求资源
cout<<"ERROR!!!线程"<<idThread<<"请求"<<idRes<<"类资源数目大于所需要的该类资源的数目!"<<endl<<endl;
return ;
}
}
for(int i=; i<res.size(); ++i){
int idRes=i, k = res[i];
resAvailable[idRes] -= k;
resAllocation[idThread][idRes] += k;
resNeed[idThread][idRes] -= k;
}
//安全性算法的检测
if(!threadAafetyDetection(idThread)){//不能分配资源, 要将idThread这个线程阻塞
for(int i=; i<res.size(); ++i){
int idRes=i, k = res[i];
resAvailable[idRes] += k;
resAllocation[idThread][idRes] -= k;
resNeed[idThread][idRes] += k;
}
return ;
}
cout<<"线程"<<idThread<<"获得资源:";
for(int i=; i<res.size(); ++i)
cout<<" "<<i<<"类:"<<res[i];
cout<<endl<<endl;
return ;
}
}; BankerAlgorithm ba; void *thread_hjzgg(void *arg){
long long idThread = (long long)arg;//得到线程的标号
srand((int)time());
//开始进行线程资源的请求
vector<int> res;
for(int i=; i<ba.nres; ++i){
int k = ba.resNeed[idThread][i] == ? : rand() % ba.resNeed[idThread][i]+;//线程对资源i申请的数目
res.push_back(k);
}
while(){
if(pthread_mutex_lock(&mutex)!=){
cout<<"线程"<<idThread<<"加锁失败!!!"<<endl;
pthread_exit(NULL);
} bool isAllocationFinished = true;//该线程是否已经将资源请求完毕
for(int i=; i<ba.nres; ++i)
if(ba.resNeed[idThread][i] != ){
isAllocationFinished = false;
break;
}
if(isAllocationFinished){
cout<<"线程"<<idThread<<"资源分配完毕!!!进程得到想要的全部资源后开始继续执行!"<<endl;
cout<<"................"<<endl;
sleep();
cout<<"线程"<<idThread<<"执行完毕!!!"<<endl<<endl; --ba.restThread;
ba.threadFinished[idThread] = ;//线程结束
ba.returnRes(idThread);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
} switch(ba.bankerAlgorithm(idThread, res)){
case ://系统会进入不安全状态,不能进行资源的分配,先进行阻塞
case ://进程阻塞
pthread_cond_wait(&cond, &mutex);
break;
case ://重新分配资源
case ://资源分配成功, 接着在申请新的资源
res.clear();
for(int i=; i<ba.nres; ++i){
int k = ba.resNeed[idThread][i] == ? : rand() % ba.resNeed[idThread][i]+;//线程对资源i申请的数目
res.push_back(k);
}
break;
default:
break;
}
sleep();
pthread_mutex_unlock(&mutex);
}
} int main(){
pthread_t tid[NTHREAD];
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
ba.init();
for(int i=; i<ba.nthread; ++i)
pthread_create(&tid[i], NULL, thread_hjzgg, (void*)i); for(int i=; i<ba.nthread; ++i)
pthread_join(tid[i], NULL);
return ;
}
/*
5 3
10 8 6
2 1 3
6 1 1
3 2 2
6 2 1
2 1 1 此时系统处于安全状态,存在线程安全序列如下:
0 1 2 3 4
线程0获得资源: 0类:2 1类:1 2类:3 此时系统处于安全状态,存在线程安全序列如下:
0 1 2 3 4
线程1获得资源: 0类:6 1类:1 2类:1 ERROR!!!线程2请求0类资源数目大于该类剩余资源的数目! 此时系统处于安全状态,存在线程安全序列如下:
0 1 2 3 4
线程4获得资源: 0类:2 1类:1 2类:1 ERROR!!!线程3请求0类资源数目大于该类剩余资源的数目! 线程0资源分配完毕!!!进程得到想要的全部资源后开始继续执行!
................
线程0执行完毕!!! 线程1资源分配完毕!!!进程得到想要的全部资源后开始继续执行!
................
线程1执行完毕!!! 线程4资源分配完毕!!!进程得到想要的全部资源后开始继续执行!
................
线程4执行完毕!!! 此时系统处于安全状态,存在线程安全序列如下:
2 3
线程3获得资源: 0类:6 1类:2 2类:1 此时系统处于安全状态,存在线程安全序列如下:
2 3
线程2获得资源: 0类:3 1类:2 2类:2 线程3资源分配完毕!!!进程得到想要的全部资源后开始继续执行!
................
线程3执行完毕!!! 线程2资源分配完毕!!!进程得到想要的全部资源后开始继续执行!
................
线程2执行完毕!!! */

c/c++多线程模拟系统资源分配(并通过银行家算法避免死锁产生)的更多相关文章

  1. 预防和避免死锁的方法及银行家算法的java简单实现

    预防死锁 (1) 摒弃"请求和保持"条件 基本思想:规定所有进程在开始运行之前,要么获得所需的所有资源,要么一个都不分配给它,直到所需资源全部满足才一次性分配给它. 优点:简单.易 ...

  2. 多任务-python实现-死锁,银行家算法(2.1.5)

    @ 目录 1.死锁 2.避免死锁的方式-银行家算法 1.死锁 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去.此时称系 ...

  3. linux多线程模拟银行家算法

    题外话: 这应该是最近有点难度的作业了,起码比之前的理发师,读写,哲学家问题要难. 但是做好程序的结构,自顶向下,就还是不难的. 银行家算法简介:                 代码: init() ...

  4. C程序模拟实现银行家算法

    C程序模拟实现银行家算法 上周又做操作系统实验,题目是用程序模拟实现银行家算法,写了半天还真有点晕,主要是因为想尽可能符合课本上的描述,所以写出来的程序就比较恶心了,好了,银行家算法就不多说了,不了解 ...

  5. [OS] 死锁相关知识点以及银行家算法详解

    因此我们先来介绍一下死锁: 死锁特征 当出现死锁时,进程永远不能完成,并且系统资源被阻碍使用,阻止了其他作业开始执行.在讨论处理死锁问题的各种方法之前,先深入讨论一下死锁的特征. ·必要条件 (1)互 ...

  6. 银行家算法之JavaScript实现

    上学期有个课程叫做操作系统,期末的时候这课程还有个课程设计,其中有个题目叫做银行家算法. 什么是银行家算法我就不解释了! 看着同学们的设计,大同小异甚至前篇一律. 清一色的控制台程序,清一色的蛋疼输入 ...

  7. C语言实现 操作系统 银行家算法

    /**************************************************** 银行家算法 算法思想: 1. 在多个进程中,挑选资源需求最小的进程Pmin. 可能存在多类资 ...

  8. java面试题之死锁产生的条件,以及如何避免死锁,银行家算法,产生死锁后如何解决(阿里面试题)

    死锁产生的四个必要条件: 互斥:一个资源每次只能被一个进程使用(资源独立) 请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不放(不释放锁) 不剥夺:进程已获得的资源,在未使用之前,不能强行 ...

  9. 操作系统——银行家算法(Banker's Algorithm)

    之前写过一篇关于死锁和银行家算法的详细描述的博客https://www.cnblogs.com/wkfvawl/p/11598647.html 写这篇博客的目的,主要是详细讲解一下银行家算法以及代码的 ...

随机推荐

  1. 【验证】C# dataSource 的记忆功能

    做项目时遇到的问题:dataSource被ComboBox引用过一次,会记忆最后一次选中的值,然后下一次再用时这个值会直接呈现在ComboBox中. 为验证是dataSource还是ComboBox自 ...

  2. js前端模块化之加载器原理解析(一)

    先来说一下前端模块化的价值:引用模块此处有详细的介绍,可以自行前往观看. 一.总结如下优点: (1)解决命名冲突(2)烦琐的文件依赖(3)模块的版本管理(4)提高可维护性(5)前端性能优化(6)跨环境 ...

  3. spring3.0使用annotation完全代替XML(续)

    从回帖的反应来看,大多数人还是不赞成完全代替XML的,这点倒是在意料之中.我个人还是倾向于用代码来取代XML的Bean定义,当然这更多的是关乎个人偏好,不代表与我观点不同的人就是错的. 先来说说代码相 ...

  4. android webView开发之js调用java代码示例

    1.webView设置 webView.getSettings().setJavaScriptEnabled(true);//设置支持js webView.addJavascriptInterface ...

  5. 在php中定义常量时,const与define的区别?

    问]在php中定义常量时,const与define的区别?  [答]使用const使得代码简单易读,const本身就是一个语言结构,而define是一个函数.另外const在编译时要比define快很 ...

  6. [LintCode] Best Time to Buy and Sell Stock II 买股票的最佳时间之二

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  7. Javascript初学篇章_7(DOM)

    DOM 文档对象模型DOM (document object model) 文档对象模型,它定义了操作文档对象的接口.DOM 把一份html文档表示为一棵家谱树,使用parent(父), child( ...

  8. $Host.Runspace.ThreadOptions = “ReuseThread”有神马用?

    $Host.Runspace.ThreadOptions = “ReuseThread” 在很多PowerShell的脚本中你都会看到这个语句被用来开头,那它的作用是什么呢? 答:这个设置可以提高对内 ...

  9. poj3122-Pie(二分法+贪心思想)

    一,题意: 有f+1个人(包括自己),n块披萨pie,给你每块pie的半径,要你公平的把尽可能多的pie分给每一个人 而且每个人得到的pie来自一个pie,不能拼凑,多余的边角丢掉.二,思路: 1,输 ...

  10. ReactJS入门(三)—— 顶层API

    本文基本跟着官方文档把API都走一遍,但会有实例来解释应该怎么用,木有比我更详细的API文档咯. React.createClass 参数:CONFIG(object) 创建一个ReactClass( ...