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

简介:

 

银行家算法数据结构 
(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=0; i<nthread; ++i)
                for(int j=0; j<nres; ++j)
                    resNeed[i].push_back(resMax[i][j]), resAllocation[i].push_back(0);
        } 
        
        bool threadAafetyDetection(int idThread){//线程安全检测 
            vector<int> tmpResAvailable(resAvailable);
            vector<int> threadSafeSequence;//线程安全序列 
            int cntThread = 0;
            memset(vis, 0, sizeof(vis));
            while(threadSafeSequence.size() < restThread){
                bool findRunThread = false;
                for(int i=0; i<nthread; ++i)
                    if(!vis[i] && !threadFinished[i]){
                        int j;
                        for(j=0; j<nres; ++j)
                            if(resNeed[i][j] > tmpResAvailable[j]) 
                                break;
                        if(j >= nres){//各类所需要的资源的数目 小于或等于各类剩余资源的数目 
                            //该进程可以成功的运行完毕
                             findRunThread = true;
                             vis[i] = 1;
                             threadSafeSequence.push_back(i);
                             for(j=0; j<nres; ++j) 
                                 tmpResAvailable[j] +=  resAllocation[i][j];
                        }
                    }
                if(!findRunThread) break;//找不到下一个可以运行的线程,则退出 
            }
            
            if(threadSafeSequence.size() == restThread){
                cout<<"此时系统处于安全状态,存在线程安全序列如下:"<<endl;
                for(int i=0; i<threadSafeSequence.size(); ++i) 
                    cout<<threadSafeSequence[i]<<" ";
                cout<<endl;
                return true;
            } else {
                cout<<"此时系统处于不安全状态!!!资源无法分配!!!进程"<<idThread<<"将被阻塞!!!"<<endl;//等到下一次resAvailable更新的时候再将该进程唤醒 
                return false;
            }
        }
        
    public:
        BankerAlgorithm(){
        }
        
        void init(){
            memset(threadFinished, 0, sizeof(threadFinished));
            //初始化线程的数目, 资源种类的数目以及每种资源的数目
            cout<<"请输入线程的数目和资源的种类数目:"<<endl;
            cin>>nthread>>nres;
            restThread = nthread; 
            cout<<"请输入每种资源的数目:" <<endl;
            for(int i=0; i<nres; ++i){
                int k;
                cin>>k;
                resAvailable.push_back(k);
            }
            
            cout<<"请输入每个线程对某类资源最大的需求:"<<endl;
            for(int i=0; i<nthread; ++i){
                cout<<"线程"<<i<<"需要的资源:"<<endl; 
                for(int j=0; j<nres; ++j){
                    int k;
                    cin>>k;
                    resMax[i].push_back(k);
                }
            }
            toNeed(); 
        }
        
        void returnRes(int idThread){
            for(int i=0; i<nres; ++i)
                resAvailable[i] += resAllocation[idThread][i], resAllocation[idThread][i]=0;
        }
        
        int bankerAlgorithm(int idThread, vector<int>res){//进程idThread对资源idRes的请求数量为k
            for(int i=0; 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 1;
                    }
                } else {//让进程重新请求资源 
                    cout<<"ERROR!!!线程"<<idThread<<"请求"<<idRes<<"类资源数目大于所需要的该类资源的数目!"<<endl<<endl; 
                    return 2;
                }
            }
            for(int i=0; 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=0; i<res.size(); ++i){
                    int idRes=i, k = res[i];
                    resAvailable[idRes] += k;
                    resAllocation[idThread][idRes] -= k;
                    resNeed[idThread][idRes] += k;
                }
                return 3; 
            }    
            cout<<"线程"<<idThread<<"获得资源:";
            for(int i=0; i<res.size(); ++i)
                cout<<" "<<i<<"类:"<<res[i];
            cout<<endl<<endl;
            return 0;
        }
};

BankerAlgorithm ba;

void *thread_hjzgg(void *arg){
    long long idThread = (long long)arg;//得到线程的标号
    srand((int)time(0));
    //开始进行线程资源的请求
    vector<int> res;
    for(int i=0; i<ba.nres; ++i){
        int k = ba.resNeed[idThread][i] == 0 ? 0 : rand() % ba.resNeed[idThread][i]+1;//线程对资源i申请的数目 
        res.push_back(k);
    }
    while(1){
        if(pthread_mutex_lock(&mutex)!=0){
            cout<<"线程"<<idThread<<"加锁失败!!!"<<endl;
            pthread_exit(NULL);
        }
        
        bool isAllocationFinished = true;//该线程是否已经将资源请求完毕 
        for(int i=0; i<ba.nres; ++i) 
            if(ba.resNeed[idThread][i] != 0){
                isAllocationFinished = false;
                break;
            }
        if(isAllocationFinished){
            cout<<"线程"<<idThread<<"资源分配完毕!!!进程得到想要的全部资源后开始继续执行!"<<endl; 
            cout<<"................"<<endl;
            sleep(1);
            cout<<"线程"<<idThread<<"执行完毕!!!"<<endl<<endl;
            
            --ba.restThread;
            ba.threadFinished[idThread] = 1;//线程结束 
            ba.returnRes(idThread);
            pthread_cond_broadcast(&cond);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
        
        switch(ba.bankerAlgorithm(idThread, res)){
            case 3://系统会进入不安全状态,不能进行资源的分配,先进行阻塞 
            case 1://进程阻塞 
                pthread_cond_wait(&cond, &mutex);
                break;
            case 2://重新分配资源 
            case 0://资源分配成功, 接着在申请新的资源 
                res.clear();
                for(int i=0; i<ba.nres; ++i){
                    int k = ba.resNeed[idThread][i] == 0 ? 0 : rand() % ba.resNeed[idThread][i]+1;//线程对资源i申请的数目 
                    res.push_back(k);
                }
                break;
            default:
                break;
        }
        sleep(1);
        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=0; i<ba.nthread; ++i)
        pthread_create(&tid[i], NULL, thread_hjzgg, (void*)i);
        
    for(int i=0; i<ba.nthread; ++i)
        pthread_join(tid[i], NULL);
    return 0;
} 
/*
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执行完毕!!!

*/









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/4820796.html,如需转载请自行联系原作者
目录
相关文章
|
4月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
99 2
|
5月前
|
存储 算法 C++
Windows共享文件:探秘C++实现的B树索引算法奇境
在数字化时代,Windows共享文件的高效管理至关重要。B树算法以其自平衡多路搜索特性,在文件索引与存储优化中表现出色。本文探讨B树在Windows共享文件中的应用,通过C++实现具体代码,展示其构建文件索引、优化数据存储的能力,提升文件检索效率。B树通过减少磁盘I/O操作,确保查询高效,为企业和个人提供流畅的文件共享体验。
|
2月前
|
算法 数据可视化 数据挖掘
基于EM期望最大化算法的GMM参数估计与三维数据分类系统python源码
本内容展示了基于EM算法的高斯混合模型(GMM)聚类实现,包含完整Python代码、运行效果图及理论解析。程序使用三维数据进行演示,涵盖误差计算、模型参数更新、结果可视化等关键步骤,并附有详细注释与操作视频,适合学习EM算法与GMM模型的原理及应用。
|
2月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
64 0
|
3月前
|
存储 机器学习/深度学习 算法
基于 C++ 的局域网访问控制列表(ACL)实现及局域网限制上网软件算法研究
本文探讨局域网限制上网软件中访问控制列表(ACL)的应用,分析其通过规则匹配管理网络资源访问的核心机制。基于C++实现ACL算法原型,展示其灵活性与安全性。文中强调ACL在企业与教育场景下的重要作用,并提出性能优化及结合机器学习等未来研究方向。
90 4
|
4月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
131 17
|
4月前
|
存储 监控 算法
基于 C# 的局域网计算机监控系统文件变更实时监测算法设计与实现研究
本文介绍了一种基于C#语言的局域网文件变更监控算法,通过事件驱动与批处理机制结合,实现高效、低负载的文件系统实时监控。核心内容涵盖监控机制选择(如事件触发机制)、数据结构设计(如监控文件列表、事件队列)及批处理优化策略。文章详细解析了C#实现的核心代码,并提出性能优化与可靠性保障措施,包括批量处理、事件过滤和异步处理等技术。最后,探讨了该算法在企业数据安全监控、文件同步备份等场景的应用潜力,以及未来向智能化扩展的方向,如文件内容分析、智能告警机制和分布式监控架构。
117 3
|
3月前
|
机器学习/深度学习 监控 算法
局域网行为监控软件 C# 多线程数据包捕获算法:基于 KMP 模式匹配的内容分析优化方案探索
本文探讨了一种结合KMP算法的多线程数据包捕获与分析方案,用于局域网行为监控。通过C#实现,该系统可高效检测敏感内容、管理URL访问、分析协议及审计日志。实验表明,相较于传统算法,KMP在处理大规模网络流量时效率显著提升。未来可在算法优化、多模式匹配及机器学习等领域进一步研究。
89 0
|
3月前
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
79 0
|
3月前
|
算法 5G 定位技术
高低频混合组网系统中基于地理位置信息的信道测量算法matlab仿真
本内容展示了一种基于地理位置信息的信道测量算法,适用于现代蜂窝系统,尤其在毫米波通信中,波束对准成为关键步骤。算法通过信号传播模型和地理信息实现信道状态测量,并优化误差提升准确性。完整程序基于Matlab2022a运行,无水印效果,核心代码配有中文注释及操作视频,适合深入学习与应用开发。

热门文章

最新文章