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的請求數量為kfor(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類:1ERROR!!!線程2請求0類資源數目大于該類剩余資源的數目!此時系統處于安全狀態,存在線程安全序列如下:
0 1 2 3 4
線程4獲得資源: 0類:2 1類:1 2類:1ERROR!!!線程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執行完畢!!!*/

?

轉載于:https://www.cnblogs.com/hujunzheng/p/4820796.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531423.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531423.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531423.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

(四)Linux內核模塊化編程

目錄&#xff08;一&#xff09;模塊化編程簡介&#xff08;二&#xff09;安裝卸載模塊命令.&#xff08;三&#xff09;將自定義功能添加到內核三種方法&#xff08;1&#xff09;修改Kconfig和Makefile&#xff08;2&#xff09;直接修改功能對應目錄下的Makefile文件&#…

基于X86平臺的PC機通過網絡發送一個int(32位)整數的字節順序

1.字節順序  字節順序是指占內存多于一個字節類型的數據在內存中的存放順序&#xff0c;通常有小端、大端兩種字節順序。小端字節序指低字節數據存放在內存低地址處&#xff0c;高字節數據存放在內存高地址處&#xff1b;大端字節序是高字節數據存放在低地址處&#xff0c;低字…

Linux內核空間和用戶空間

在Linux系統中存在進程的概念&#xff1a; 進程的分類&#xff1a; 用戶進程&#xff1a;運行在用戶空間的進程被稱為用戶進程 內核進程:運行在內核空間的進程被稱為內核進程 進程的空間&#xff1a; 系統會為每一個進程分0-4G的虛擬尋址空間&#xff0c;在4G的空間中 0-3G&…

codeforces Round #320 (Div. 2) C. A Problem about Polyline(數學) D. Or Game(暴力,數學)

解題思路&#xff1a;就是求數 n 對應的二進制數中有多少個 1 #include <iostream> #include<cstdio> using namespace std; int main(){int n;cin>>n;int ans 0; // while(n){//這也是一種好的方法 // n n&(n-1); // ans; // }while(n…

(五)Linux之設備驅動模型

目錄&#xff08;一&#xff09;Linux內核驅動簡介&#xff08;二&#xff09;雜項設備驅動模型&#xff08;1&#xff09;相關接口&#xff08;2&#xff09;雜項設備注冊過程&#xff08;三&#xff09;早期經典字符設備驅動模型&#xff08;1&#xff09;相關接口&#xff0…

操作系統頁面置換算法(opt,lru,fifo,clock)實現

選擇調出頁面的算法就稱為頁面置換算法。好的頁面置換算法應有較低的頁面更換頻率&#xff0c;也就是說&#xff0c;應將以后不會再訪問或者以后較長時間內不會再訪問的頁面先調出。 常見的置換算法有以下四種&#xff08;以下來自操作系統課本&#xff09;。 1. 最佳置換算法(…

(六)Linux之設備驅動模型(續)

前面我們學習了雜項設備驅動模型、早期經典字符設備驅動模型,這一小節來講解Linux中的標準字符設備驅動。 目錄&#xff08;一&#xff09;為什么引入標準字符設備驅動模型&#xff08;二&#xff09;相關接口&#xff08;三&#xff09;注冊流程&#xff08;四&#xff09;程序…

N個數依次入棧,出棧順序有多少種?

對于每一個數來說&#xff0c;必須進棧一次、出棧一次。我們把進棧設為狀態‘1’&#xff0c;出棧設為狀態‘0’。n個數的所有狀態對應n個1和n個0組成的2n位二進制數。由于等待入棧的操作數按照1‥n的順序排列、入棧的操作數b大于等于出棧的操作數a(a≤b)&#xff0c;因此輸出序…

(七)linux函數接口的使用

前面我們講解了字符設備的驅動模型&#xff0c;有了前面的基礎后&#xff0c;今天學習函數接口就比較容易了 目錄&#xff08;一&#xff09;open函數接口&#xff08;二&#xff09;read函數接口&#xff08;三&#xff09;lseek函數接口&#xff08;四&#xff09;用戶空間和…

(八)linux驅動之ioctl的使用

這篇文章給大家講解一下ioctl的簡單使用&#xff0c;關于ioctl更詳細的教程后面有機會單獨寫出來 &#xff08;一&#xff09;什么是ioctl ioctl是設備驅動程序中對設備的I/O通道進行管理的函數。所謂對I/O通道進行管理&#xff0c;就是對設備的一些特性進行控制&#xff0c;例…

(九)linux中斷編程

目錄&#xff08;一&#xff09;linux中斷的介紹&#xff08;二&#xff09;內核中斷的操作過程&#xff08;三&#xff09;實例代碼&#xff08;一&#xff09;linux中斷的介紹 linux內核中的中斷通過中斷子系統來管理。linux系統中有專門的中斷子系統&#xff0c;原理很復雜…

網絡爬蟲(1)

參考&#xff1a;http://www.cnblogs.com/dongkuo/p/4851735.html算法分析我們現在從需求中提取關鍵詞來逐步分析問題。 首先是“種子節點”。它就是一個或多個在爬蟲程序運行前手動給出的URL&#xff08;網址&#xff09;&#xff0c;爬蟲正是下載并解析這些種子URL指向的頁面…

(十)Linux之等待隊列

&#xff08;一&#xff09;阻塞和非阻塞 阻塞&#xff1a;執行設備操作時&#xff0c;若不能獲得資源&#xff0c;則掛起進程進入休眠直到滿足可操作的條件后再操作。 非阻塞&#xff1a;進程在不能進行設備操作時&#xff0c;并不掛起&#xff0c;它要么放棄&#xff0c;要么…

(十一)linux之poll輪詢

目錄&#xff08;一&#xff09;poll輪詢的作用&#xff08;二&#xff09;poll輪詢相關的接口&#xff08;三&#xff09;poll使用流程&#xff08;四&#xff09;實例代碼&#xff08;一&#xff09;poll輪詢的作用 以阻塞的方式打開文件&#xff0c;那么對多個文件讀寫時&a…

校驗碼(海明校驗,CRC冗余校驗,奇偶校驗)

循環冗余校驗碼 CRC碼利用生成多項式為k個數據位產生r個校驗位進行編碼,其編碼長度為nkr所以又稱 (n,k)碼. CRC碼廣泛應用于數據通信領域和磁介質存儲系統中. CRC理論非常復雜,一般書就給個例題,講講方法.現在簡單介紹下它的原理: 在k位信息碼后接r位校驗碼,對于一個給定的(n,k…

(十二)linux內核定時器

目錄&#xff08;一&#xff09;內核定時器介紹&#xff08;二&#xff09;內核定時器相關接口&#xff08;三&#xff09;使用步驟&#xff08;四&#xff09;實例代碼&#xff08;一&#xff09;內核定時器介紹 內核定時器并不是用來簡單的定時操作&#xff0c;而是在定時時…

java Proxy(代理機制)

我們知道Spring主要有兩大思想&#xff0c;一個是IoC&#xff0c;另一個就是AOP&#xff0c;對于IoC&#xff0c;依賴注入就不用多說了&#xff0c;而對于Spring的核心AOP來說&#xff0c;我們不但要知道怎么通過AOP來滿足的我們的功能&#xff0c;我們更需要學習的是其底層是怎…

(十三)linux中斷底半部分處理機制

這篇文章介紹一下linux中斷的底半部分的tasklet和workquene兩種處理機制&#xff0c;其中tasklet中不能有延時函數&#xff0c;workquene的處理函數可以加入延時操作 目錄&#xff08;一&#xff09;tasklet小任務處理機制&#xff08;1&#xff09;tasklet相關函數接口&#x…

Codeforces Round #326 (Div. 2) B. Pasha and Phone C. Duff and Weight Lifting

B. Pasha and PhonePasha has recently bought a new phone jPager and started adding his friends phone numbers there. Each phone number consists of exactly n digits. Also Pasha has a number k and two sequences of length n?/?k (n is divisible by k) a1,?a2,?…

vmware中裝的ubuntu上不了網

本文章針對橋接方式進行講解&#xff0c;如果需要另外兩種連接方式請參考文末給出的鏈接 &#xff08;一&#xff09;問題 主機和虛擬機可以相互ping通&#xff0c;但是卻不能ping網址 &#xff08;二&#xff09;解決辦法 vmware為我們提供了三種網絡工作模式&#xff0c;…