銀行家算法簡易實現

這里寫目錄標題

  • 實驗要求
  • 內容
  • 代碼
    • main.cpp
    • myfunc.h
    • myfunc.cpp
  • 運行結果與分析

實驗要求

程序可以針對不同進程的請求進行判斷,并決定是否滿足其需求。算法程序需要設計合理的數據結構,對資源情況、進程相關數據進行存儲。

內容

隨機生成數據, 并校驗數據是否會產生死鎖問題

實現銀行家算法的核心: 安全性算法, 銀行家算法的請求判斷

打印每個線程的合法請求向量序列

打印銀行家算法一次接受的請求向量序列

代碼

main.cpp

#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <stdbool.h>
#include <set>
#include <vector>
#include "myfunc.h"// 5 個進程, 3類資源
#define NUM_RESOURCES 3
#define NUM_PROCESSES 5
#define MAX_RES_NUM 10#define Lock(x) pthread_mutex_lock(x)
#define UnLock(x) pthread_mutex_unlock(x)// 因為只有一個資源分配處理器, 所以各線程需要互斥地申請資源
pthread_mutex_t mutex;
// 銀行家算法需要用到的數據結構
std::vector<int> available(NUM_RESOURCES);
std::vector<std::vector<int>>maximum(NUM_PROCESSES, std::vector<int>(NUM_RESOURCES));
std::vector<std::vector<int>>need(NUM_PROCESSES, std::vector<int>(NUM_RESOURCES));
std::vector<std::vector<int>>allocation(NUM_PROCESSES, std::vector<int>(NUM_RESOURCES));
/*** 初始化可用資源
*/
void init_resources() {for (int i = 0; i < NUM_RESOURCES; i++) {// [0, MAX_RES_NUM]available[i] = rand() % MAX_RES_NUM + 1;}
}
/*** 初始化每個線程對每個資源的最大需求, 不超過available* (雖然本人絕對這個maximum和need沒多大區別)
*/
void init_maximum() {for (int i = 0; i < NUM_PROCESSES; i++) {for (int j = 0; j < NUM_RESOURCES; j++) {// [0, available[j]]maximum[i][j] = rand() % (available[j] + 1);}}
}/*** 初始化分配矩陣* 初值為0 
*/ 
void init_allocation() {for (int i = 0; i < NUM_PROCESSES; i++) {for (int j = 0; j < NUM_RESOURCES; j++) {allocation[i][j] = 0;}}
}// 初始化需求矩陣
void init_need() {for (int i = 0; i < NUM_PROCESSES; i++) {for (int j = 0; j < NUM_RESOURCES; j++) {need[i][j] = maximum[i][j] - allocation[i][j];}}
}/*** 安全性算法:* 在某時刻, 查看當前可用資源向量面對, need矩陣是否處于安全狀態* 即是否可以找到一個安全序列, 安全序列并不是唯一的, * 能找出一個安全序列即可證明當前的available處于安全狀態
*/
std::vector<int> process_ids(NUM_PROCESSES);
bool check_safe() {// work是當前可分配的資源向量std::vector<int> work(available);// 保存安全序列(有必要可以打印調試)std::vector<int> safe_seq;std::set<int> pids(process_ids.begin(), process_ids.end());for (int i = 0; i < process_ids.size(); i++) {// 檢查need矩陣的每一行, 如果該行對應的需求向量 <= workfor (auto pid : pids) {if (need[pid] <= work) {safe_seq.push_back(pid);work += allocation[pid];pids.erase(pid);break;}}}// 如果能找到一個包含所有線程的安全序列if (safe_seq.size() == process_ids.size()) {return true;}return false;
}
// path保存每個線程的請求向量
std::vector<std::vector<std::vector<int>>> path(NUM_PROCESSES);
// schedule保存處理器調度請求向量的順序和對應的線程編號
std::vector<std::pair<int, std::vector<int>>> schedule;
/*** 向處理器發起資源分配請求* 利用銀行家算法處理請求與分配
*/
void* request_banker(void *arg) {int process_id = *((int *)arg);while (true) {Lock(&mutex);// 隨機為當前進程構造請求向量std::vector<int> request(NUM_RESOURCES);for (int i = 0; i < NUM_RESOURCES; i++) {request[i] = rand() % (need[process_id][i] + 1);}// 請求的資源 > 當前剩余的資源, // 則讓出cpu, 重新生成一個合理的reqif (request > available) {UnLock(&mutex);continue;}// 如果隨機生成的req=0, 則重新生成if (request == std::vector<int>(NUM_RESOURCES, 0)) {UnLock(&mutex);continue;}// 給當前線程分配資源for (int i = 0; i < NUM_RESOURCES; i++) {available[i] -= request[i];allocation[process_id][i] += request[i];need[process_id][i] -= request[i];}// 如果給當前進程分配了它所請求的資源// 但是進入了不安全的狀態, 則撤銷此次分配資源if (!check_safe()) {for (int i = 0; i < NUM_RESOURCES; i++) {available[i] += request[i];allocation[process_id][i] -= request[i];need[process_id][i] += request[i];}// 如果該請求向量, 會使得當前狀態進入不安全的狀態// 則該請求非法, 讓其它線程請求printf("Process %d is Waiting\n", process_id);print_vector(need[process_id]);UnLock(&mutex);continue;} // 調試信息保存path[process_id].push_back(request);schedule.push_back(std::make_pair(process_id, request));if (need[process_id] == std::vector<int>(NUM_RESOURCES, 0)) {printf("Process %d have completed.\n", process_id);// 一個線程完成他的操作后要釋放占用的資源????available += allocation[process_id];for (auto p : path[process_id]) {print_vector(p);}UnLock(&mutex);// break使得該線程結束break;} UnLock(&mutex);}
}
/*** 檢查是否滿足銀行家算法的先決條件* 假設有n個線程, m種資源, 每種資源k[i](i=0, ..., m-1)個* 使得不產生死鎖的充分條件為: 每種資源的總需求和 <= n + m[i] - 1* 即滿足該條件一定不會發生死鎖, 但是不滿足只是可能會產生死鎖* 這里所謂死鎖為: * 當前未完成的線程集合中的任意一個線程的任意一個請求都不能被銀行家算法接受* 從而導致每個線程都在持續的做無用的請求* 例如: 當前有n=3個線程, m=1種資源, 數量為3* 每個線程的需求need如下*   alloc need avail* A:  0    1    3* B:  0    1* C:  0    4* 線程A最多請求1個資源, 如果滿足線程A, 則剩余2個資源, 不能滿足其余的線程, 進入不安全狀態, 拒絕此請求* 線程B最多請求1個資源, 如果滿足線程B, 則剩余2個資源, 不能滿足其余的線程, 進入不安全狀態, 拒絕此請求* 線程C最少請求一個資源, 如果滿足線程C, 則剩余2個資源, * 如果接受C的下限請求, 下一個狀態也為不安全狀態*   alloc need avail* A:  0    1    2* B:  0    1* C:  1    3* 最終會不會發生死鎖, 取決于調度, 如果敲好串行的調度這些線程的請求, * 則肯定不會發生死鎖, 否則有可能發生
*/
bool check_prerequisite() {std::vector<int> colsum(NUM_RESOURCES);for (int i = 0; i < NUM_PROCESSES; i++) {int rowsum = 0;for (int j = 0; j < NUM_RESOURCES; j++) {if (maximum[i] == std::vector<int>(NUM_PROCESSES, 0)) {return false;}colsum[j] += maximum[i][j];rowsum += maximum[i][j];}if (rowsum == 0) return false;}for (int i = 0; i < NUM_RESOURCES; i++) {if (NUM_PROCESSES + available[i] - 1 > colsum[i]) {return false;}}return true;
}
void init() {init_resources();init_maximum();init_allocation();init_need();
}int main() {std::vector<pthread_t> threads(NUM_PROCESSES);srand(time(NULL));// 初始化互斥鎖pthread_mutex_init(&mutex, nullptr);// 隨機生成可用資源// 直到生成的數據不會發生死鎖init_resources();printf("prerequisite[] => ");for (int i = 0; i < NUM_RESOURCES; i++) {printf("%d ", NUM_PROCESSES + available[i]);}printf("\n");// 保證生成的數據不會有死鎖問題do {init_maximum();} while (check_prerequisite());init_allocation();init_need();printf("available[] => ");print_vector(available);printf("need[][] => \n");for (int i = 0; i < NUM_PROCESSES; i++) {print_vector(need[i]);}// 創建進程線程for (int i = 0; i < NUM_PROCESSES; i++) {process_ids[i] = i;pthread_create(&threads[i], nullptr, request_banker, &process_ids[i]);}// 等待所有線程結束for (int i = 0; i < NUM_PROCESSES; i++) {pthread_join(threads[i], nullptr);}printf("A safe cpu schedule: \n");for (auto [pid, req] : schedule) {printf("Process %d : ", pid);print_vector(req);}// 銷毀互斥鎖pthread_mutex_destroy(&mutex);return 0;
}

myfunc.h

#ifndef MYFUNC_H
#define MYFUNC_H#include <vector>
#include <stdio.h>
// 聲明一個函數,用于比較兩個 vector<int> 是否相等
void print_vector(std::vector<int> v);
bool operator==(const std::vector<int>& v1, const std::vector<int>& v2);
bool operator<=(const std::vector<int>& v1, const std::vector<int>& v2);
bool operator<(const std::vector<int>& v1, const std::vector<int>& v2);
bool operator>(const std::vector<int>& v1, const std::vector<int>& v2);
std::vector<int>& operator+=(std::vector<int>& v1, const std::vector<int>& v2);
std::vector<int>& operator-=(std::vector<int>& v1, const std::vector<int>& v2);
std::vector<int> operator+(const std::vector<int>& v1, const std::vector<int>& v2);
#endif

myfunc.cpp

#include "myfunc.h"
void print_vector(std::vector<int> v) {if (v.empty()) return;printf("[");for (int i = 0; i < v.size(); i++) {if (i != v.size() - 1) {printf("%d, ", v[i]);} else {printf("%d]\n", v[i]);}}
}
bool operator==(const std::vector<int>& v1, const std::vector<int>& v2) {// 檢查向量的大小是否相等if (v1.size() != v2.size()) {return false;}// 逐個比較向量的元素for (std::size_t i = 0; i < v1.size(); ++i) {if (v1[i] != v2[i]) {return false;}}return true;
}
bool operator<=(const std::vector<int>& v1, const std::vector<int>& v2) {// 檢查向量的大小是否相等if (v1.size() != v2.size()) {return false;}// 逐個比較向量的元素for (std::size_t i = 0; i < v1.size(); ++i) {if (v1[i] > v2[i]) {return false;}}return true;
}
bool operator>(const std::vector<int>& v1, const std::vector<int>& v2) {return !(v1 <=v2);
}
bool operator<(const std::vector<int>& v1, const std::vector<int>& v2) {// 檢查向量的大小是否相等if (v1.size() != v2.size()) {return false;}// 逐個比較向量的元素for (std::size_t i = 0; i < v1.size(); ++i) {if (v1[i] >= v2[i]) {return false;}}return true;
}
std::vector<int>& operator+=(std::vector<int>& v1, const std::vector<int>& v2) {if (v1.size() != v2.size()) {throw nullptr;}for (std::size_t i = 0; i < v1.size(); ++i) {v1[i] += v2[i];}return v1;
}
std::vector<int>& operator-=(std::vector<int>& v1, const std::vector<int>& v2) {if (v1.size() != v2.size()) {throw nullptr;}for (std::size_t i = 0; i < v1.size(); ++i) {v1[i] -= v2[i];}return v1;
}
std::vector<int> operator+(const std::vector<int>& v1, const std::vector<int>& v2) {if (v1.size() != v2.size()) {return std::vector<int>();}std::vector<int> result;result.reserve(v1.size());for (std::size_t i = 0; i < v1.size(); ++i) {result.push_back(v1[i] + v2[i]);}return result;
}

運行結果與分析

保證沒有死鎖的數據, 運行結果

available[] => [2, 7, 1]
need[][] =>
[0, 3, 1]
[1, 3, 0]
[0, 0, 1]
[0, 5, 1]
[1, 0, 1]
Process 0 have completed.
[0, 3, 0]
[0, 0, 1]
Process 1 have completed.
[1, 3, 0]
Process 2 have completed.
[0, 0, 1]
Process 4 have completed.
[1, 0, 0]
[0, 0, 1]
Process 3 have completed.
[0, 5, 0]
[0, 0, 1]
A safe cpu schedule: 
Process 0 : [0, 3, 0]
Process 0 : [0, 0, 1]
Process 1 : [1, 3, 0]
Process 2 : [0, 0, 1]
Process 4 : [1, 0, 0]
Process 4 : [0, 0, 1]
Process 3 : [0, 5, 0]
Process 3 : [0, 0, 1]

修改程序片段為

do {init_maximum();} while (!check_prerequisite());

生成可能會產生死鎖的數據, 但是沒有調度出死鎖的情況

available[] => [9, 8, 7]
need[][] =>
[2, 3, 6]
[6, 2, 2]
[7, 7, 2]
[4, 0, 0]
[2, 5, 7]
Process 0 is Waiting
[2, 3, 6]
Process 0 have completed.
[1, 1, 2]
[0, 0, 2]
[0, 2, 2]
[1, 0, 0]
Process 1 have completed.
[6, 2, 1]
[0, 0, 1]
Process 3 have completed.
[1, 0, 0]
[2, 0, 0]
[1, 0, 0]
Process 4 have completed.
[2, 5, 6]
[0, 0, 1]
Process 2 have completed.
[1, 3, 1]
[5, 4, 0]
[0, 0, 1]
[1, 0, 0]
A safe cpu schedule:
Process 0 : [1, 1, 2]
Process 0 : [0, 0, 2]
Process 0 : [0, 2, 2]
Process 0 : [1, 0, 0]
Process 1 : [6, 2, 1]
Process 1 : [0, 0, 1]
Process 3 : [1, 0, 0]
Process 3 : [2, 0, 0]
Process 3 : [1, 0, 0]
Process 4 : [2, 5, 6]
Process 4 : [0, 0, 1]
Process 2 : [1, 3, 1]
Process 2 : [5, 4, 0]
Process 2 : [0, 0, 1]
Process 2 : [1, 0, 0]

生成可能會產生死鎖的數據, 調度出死鎖的情況

available[] => [10, 6, 8]
need[][] => 
[2, 0, 5]
[4, 6, 3]
[6, 2, 1]
[5, 3, 2]
[4, 4, 8]
Process 0 is Waiting
[2, 0, 5]
Process 4 is Waiting
[4, 4, 8]
Process 4 is Waiting
[2, 4, 8]
Process 0 have completed.
[1, 0, 4]
[0, 0, 1]
[1, 0, 0]
.....
此后程序阻塞...

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

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

相關文章

做視頻號小店,怎么找達人合作?這里有詳細講解

大家好&#xff0c;我是電商笨笨熊 做視頻號小店是沒有自然流量的&#xff0c;這點剛入駐的新玩家還不清楚&#xff1b; 因此很多老電商玩家們還想著繼續拿其他平臺動銷自然流的玩法去做視頻號&#xff1b; 只能說這種方式在視頻號是完全行不通的&#xff0c;當下想要推廣售…

設計模式2——原則篇:依賴倒轉原則、單一職責原則、合成|聚合復用原則、開放-封閉原則、迪米特法則、里氏代換原則

設計模式2——設計原則篇 目錄 一、依賴倒轉原則 二、單一職責原則&#xff08;SRP&#xff09; 三、合成|聚合復用原則&#xff08;CARP&#xff09; 四、開放-封閉原則 五、迪米特法則&#xff08;LoD&#xff09; 六、里氏代換原則 七、接口隔離原則 八、總結 一、依賴…

Python-VBA函數之旅-setattr函數

目錄 一、setattr函數的常見應用場景 二、setattr函數使用注意事項 三、如何用好setattr函數&#xff1f; 1、setattr函數&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推薦閱讀&#xff1a; 個人主頁&#xff1a; https://blog.csdn.net/ygb_1024?…

宏集Panorama SCADA軟件獲BACnet BTL認證

Panorama 獲得BACnet BTL認證 建筑物的組件&#xff08;空調系統、照明傳感器等&#xff09;能否使用共同通訊協議&#xff1f;這正是標準化 BACnet協議&#xff08;Building Automation and Control Networks&#xff09;所提供的功能。該協議旨在實現建筑物中各種設備和系統…

【TS】入門

創建項目 vscode自動編譯ts 生成配置文件 tsc --init 然后發現終端也改變了&#xff1a;

SOCKET編程(3):相關結構體與函數

相關結構體與函數 sockaddr、sockaddr_in結構體 sockaddr和sockaddr_in詳解 struct sockaddr共16字節&#xff0c;協議族(family)占2字節&#xff0c;IP地址和端口號在sa_data字符數組中 /* Structure describing a generic socket address. */ struct sockaddr {__SOCKADDR…

抓大鵝教程電腦端秒通關……

大家好&#xff0c;我是小黃。 最近抓大鵝小程序游戲很火&#xff0c;抓大鵝小游戲是由青島藍飛互娛科技股份有限公司開發并推出的一款休閑益智類三消游戲。在游戲中&#xff0c;玩家需要在特定的“購物籃子”背景下&#xff0c;找到三個相同的物品并將其消除。游戲的玩法簡單…

社工庫信息查詢

此網站需要注冊賬號&#xff0c;新用戶注冊送3點券&#xff0c;每日簽到可獲得1.5點券。也可通過充值來查 我這里有方法可以利用缺陷來無限獲取點券查人

Python 實戰之量化交易

1. Python 實戰之量化交易 2..Python量化交易實戰-04.量化交易系統架構的設計 Python量化交易實戰-04.量化交易系統架構的設計 - 知乎 3.Python量化交易實戰-06.通過PythonAPI獲取股票數據 Python量化交易實戰-06.通過PythonAPI獲取股票數據 - 知乎 3.Python量化交易實戰…

程序員的歸宿。。

大家好&#xff0c;我是瑤琴呀。 相信每個進入職場的人都考慮過自己的職業生涯規劃&#xff0c;在不同的年齡段可能面臨不同挑戰&#xff0c;這點對于 35 的人應該更為感同身受。 對于程序員來說&#xff0c;大部分人的職業道路主要是下面三種&#xff1a;第一條&#xff0c;…

【Delphi 爬蟲庫 6】使用正則表達式提取貓眼電影排行榜top100

正則表達式庫的簡單介紹 正則表達式易于使用&#xff0c;功能強大&#xff0c;可用于復雜的搜索和替換以及基于模板的文本檢查。這對于輸入形式的用戶輸入驗證特別有用-驗證電子郵件地址等。您還可以從網頁或文檔中提取電話號碼&#xff0c;郵政編碼等&#xff0c;在日志文件中…

人生是曠野,不是軌道

最近看到一句話&#xff0c;很喜歡&#xff0c;分享一下。"人生是曠野&#xff0c;不是軌道"。人生不是固定的方程式&#xff0c;也沒有唯一答案&#xff0c;沒有誰生來就應該是什么樣。別太被太多世俗觀念束縛住手腳&#xff0c;每個人都有權利自由生長&#xff0c;…

用友暢捷通T+ keyEdit sql注入漏洞

產品介紹 暢捷通 T 是一款靈動&#xff0c;智慧&#xff0c;時尚的基于互聯網時代開發的管理軟件&#xff0c;主要針對中小型工貿與商貿企業&#xff0c;尤其適合有異地多組織機構&#xff08;多工廠&#xff0c;多倉庫&#xff0c;多辦事處&#xff0c;多經銷商&#xff09;的…

朋友圈刷屏的粘土風格照片,你體驗過了嗎?

Remini 的粘土風格真的丑萌丑萌的&#xff01; 從去年“妙鴨相機”的走紅&#xff0c;到今年Remini的刷屏&#xff0c;其實可以看出大眾對于圖片趣玩的興趣非常大&#xff01; 一張普通的照片經過工具的處理&#xff0c;一下子變成新風格&#xff0c;讓人眼前一亮。如果你也對…

GPT-SoVits:語音克隆,語音融合

首發網站 https://tianfeng.space 前言 零樣本文本到語音&#xff08;TTS&#xff09;&#xff1a; 輸入 5 秒的聲音樣本&#xff0c;即刻體驗文本到語音轉換。少樣本 TTS&#xff1a; 僅需 1 分鐘的訓練數據即可微調模型&#xff0c;提升聲音相似度和真實感。跨語言支持&…

信息收集方法合集 第1期

前言 在工作中&#xff0c;經常被問到某個文件怎么下載&#xff0c;原文來自哪里。索性把我知道的所有信息收集方法全部整理一遍&#xff0c;希望對大家有用&#xff0c;如果有幫助到你&#xff0c;非常榮幸&#xff0c;我會堅持分享我的學習、工作經驗。 信息種類&#xff1…

如何用java編寫一個猜數字游戲

我想到用c能編出一個猜數字游戲&#xff0c;于是我就嘗試用java編寫一個 代碼如下&#xff1a; import java.util.Scanner; import java.util.Random;public class GuessTheNumber {public static void main(String[] args) {Scanner scanner new Scanner(System.in);Random…

云啟未來:“云計算與網絡運維精英交流群”與“獨家資料”等你來探索“

作者簡介&#xff1a;一名云計算網絡運維人員、每天分享網絡與運維的技術與干貨。 公眾號&#xff1a;網絡豆云計算學堂 座右銘&#xff1a;低頭趕路&#xff0c;敬事如儀 個人主頁&#xff1a; 網絡豆的主頁????? &#x1f680; 云計算與運維精英交流群誠邀您的加入…

搭建Docker私服鏡像倉庫Harbor

1、概述 Harbor是由VMware公司開源的企業級的Docker Registry管理項目&#xff0c;它包括權限管理(RBAC)、LDAP、日志審核、管理界面、自我注冊、鏡像復制和中文支持等功能。 Harbor 的所有組件都在 Dcoker 中部署&#xff0c;所以 Harbor 可使用 Docker Compose 快速部署。 …

PermissionError: [Errno 13] Permission denied: ‘xx.xlsx‘的解決辦法

我在轉換文件的時候遇到這個報錯&#xff0c;原因是文件名與已有文件名重復了 解決辦法很簡單&#xff0c;如下圖把" " 里的名字換成不重復的&#xff0c;再次允許代碼&#xff0c;會恢復正常