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

#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执行完毕!!!

*/
 
时间: 2024-11-03 05:44:24

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

操作系统之银行家算法避免死锁

银行家算法避免死锁 要求: 完成程序数据结构的设计,数据的录入. 完成进程需求矩阵的输出,包括最大需求矩阵,尚需资源矩阵,可获得资源显示. 完成某进程请求资源试分配. 完成安全性检查. 1.         试探分配 当进程pi提出资源申请时,系统执行下列步骤: (1)若Request[i][j]≤Need[i][j],转(2): 否则错误返回 (2)若Request[i][j]≤Available[j], 转(3):否则进程等待 (3)试探着把资源分配给进程Pi,则有: Available[j

银行家算法避免死锁

系统安全状态的定义 1.安全状态 在避免死锁的方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性.若此次分配不会导致系统进入不安全状态,则将资源分配给进程:否则,令进程等待. 虽然并非所有的不安全状态都必然会转为死锁状态,但当系统进入不安全状态后,便有可能进而进入死锁状态:反之,只要系统处于安全状态,系统便可避免进入死锁状态. 因此,避免死锁的实质在于:系统在进行资源分配时,如何使系统不进入不安全状态. 利用银行家算法避免死锁 1.银行家算法中的数据结构 (1

利用银行家算法避免死锁的介绍与举例

一.数据结构 1.多个进程: { P0,P1,P2,P4 } 代表1,2,3,4四个需要临界资源的进程 2.几种资源:{ A, B ,C } 代表A,B,C三种临界资源 3.Max:最大需求矩阵(进程完成执行需要的各资源总量)   Allocation:分配矩阵(某个进程现在已经拥有的各资源量)   Need:需求矩阵(某个进程仍需要的各资源量)   Available:可利用资源向量 (系统保有的供分配的资源量)   其中:Need = Max - Allocation ,很容易理解嘛,仍然需

银行家算法:解决多线程死锁问题

死锁: 死锁产生的现场:当A进程P S2信号量而B进程P S1信号量时就会产生死锁,因为S2信号量需要B进程释放,而S1信号量需要A进程释放,因此两个进程都在等相互的资源,造成死锁. 死锁产生的条件: 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用.(信号量s1 s2为互斥的信号量,只能被一个进程占用) 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放.(A进程在获取s2阻塞时,一直占用s1) 不可剥夺条件:进程已获得的资源在未使用完之前,不

银行家算法学习笔记

     上周操作系统的实验,就是模拟实现银行家算法,首先我们还是应该对银行家算法熟悉一下. 银行家算法是最具代表性的避免死锁的算法.因为该算法原本是为银行系统设计的,以确保银行在发放现金贷款时,不会发生不满足所有客户需求的情况.在OS中也可它来实现避免死锁. 算法概述: 为实现银行家算法,每一个进程在进入系统时,它必须申明在运行过程中,可能需要每种资源类型的最大单元数目,其数目不应超过系统所拥有的资源总量,当进程请求一组资源时,系统必须首先确定是否有足够的资源分配给该进程.若有,再进一步计算在

银行家算法实例(转)

在网上找了一篇不可多的的讲银行家算法的例题的博文,mark下来.作者写的还是不错,简单易懂,比单纯讲含义要实用的多. 转自: 木轩琰的博客 最近开始备考计算机四级,基本没有遇到什么问题,感觉计算机四级就是考理解型记忆力,银行家算法的题算是在计算机四级里少有的计算题. 例1.设系统中有三种类型的资源(A,B,C)和五个进程(P1,P2,P3,P4,P5),A资源的数量是17,B资源的数量是6,C资源的数量为19.在T0时刻系统的状态如下表:   最大资源需求量 已分配资源量   A,B,C A,B

避免死锁的银行家算法

多线程操作系统在进程调度(资源分配)的时候可能会发生死锁. 引起死锁的直接原因是竞争不可抢占的互斥资源.这种资源有可能是临界资源,例如打印机:也有可能是可消耗性资源,例如信号量. 引起死锁的间接原因进程推进顺序不当.即系统单独运行进程P1或者P2都没有问题,但是调度两个进程同时进行时,由于调度顺序导致两个进程竞争资源产生死锁. ----------------------------- 产生死锁的四个必要条件: 1.互斥条件.进程已经分配到的资源具有互斥性,不能同时被其他进程共享. 2.请求和保

操作系统—银行家算法

参考http://blog.csdn.net/yaopeng_2005/article/details/6935235 对小鹏_加油的代码进行了部分修改,并加入了自己的文档注释 定义全局变量,以及主函数main 1 #include <iostream> 2 using namespace std; 3 #define MAXPROCESS 50 //最大进程数 4 #define MAXRESOURCE 100 //最大资源数 5 int AVAILABLE[MAXRESOURCE]; //

银行家算法

我们可以把操作系统作为一个银行家.操作系统管理的资金相当于银行家的资源.过程向操作系统请求分配相当于用户资源,银行贷款. 为了保证资金的安全性,银行规定: (1) 当资金客户最大需求不超过可用资金的银行家可以接受客户; (2) 贷款,但贷款的总数不能超过最大需求量; (3) 当银行家现有的资金不能满足顾客尚需的贷款数额时,对顾客的贷款可推迟支付,但总能使顾客在有限的时间里得到贷款; (4) 当顾客得到所需的所有资金后,一定能在有限的时间里归还所有的资金. 银行家算法数据结构 1)可利用资源向量A