一、概述
银行家算法(Banker's Algorithm)是一种经典的死锁避免算法,由计算机科学家Edsger Dijkstra在1965年提出。它主要用于操作系统中的资源分配,确保系统能够安全地进行资源分配和释放,避免因资源分配不当而导致的死锁。银行家算法的基本思想类似于银行在贷款时要保证其有足够的资金以应对所有客户的最大需求,以免因资金周转不灵而导致破产。
二、原理
银行家算法通过对系统当前状态和资源请求进行检查,来确保系统能够安全地分配资源。它通过模拟资源分配和检查系统是否进入安全状态来决定是否批准资源请求。
1. 系统模型
在银行家算法中,系统模型包括以下几个参数:
n
:进程的数量。m
:资源类型的数量。Available
:长度为m
的数组,表示系统当前可用的各类资源数目。Max
:n*m
的矩阵,表示每个进程对各类资源的最大需求。Allocation
:n*m
的矩阵,表示每个进程当前已分配到的各类资源数目。Need
:n*m
的矩阵,表示每个进程尚需的各类资源数目。Need[i][j] = Max[i][j] - Allocation[i][j]
。
2. 安全性检查
银行家算法在进行资源分配前,会进行安全性检查,即在分配资源后,系统是否能够进入一个安全状态。安全状态是指系统中存在一个进程序列,使得每个进程能够在其最大需求得到满足后顺利执行完毕。
三、银行家算法步骤
银行家算法分为以下几个步骤:
- 初始化系统状态:设置初始的
Available
、Max
、Allocation
和Need
矩阵。 - 请求资源:当进程请求资源时,检查请求是否合法(即请求量不超过进程的最大需求和系统的可用资源)。
- 试探性分配:临时分配资源给进程,并更新系统状态。
- 安全性检查:调用安全性算法检查系统是否处于安全状态。如果安全,正式分配资源;否则,恢复原状态,拒绝请求。
四、银行家算法实例
假设有如下系统状态:
- 资源类型:A、B、C
- 进程数:5
- 各资源的总数:A(10),B(5),C(7)
初始状态如下:
运行结果
当运行上述代码时,如果进程P1(即process_id = 1
)请求资源[1, 0, 2],系统将检查该请求是否会导致系统进入不安全状态。如果安全,则批准请求并更新系统状态;否则,拒绝请求并恢复原始状态。
通过这种方式,银行家算法有效地避免了死锁问题,确保了系统的安全运行。
Available
= [3, 3, 2]Max
矩阵:- [7, 5, 3],
[3, 2, 2],
[9, 0, 2],
[2, 2, 2],
[4, 3, 3] Allocation
矩阵:- [0, 1, 0],
- [2, 0, 0],
- [3, 0, 2],
- [2, 1, 1],
- [0, 0, 2]
Need
矩阵(由Max - Allocation
得出):- [7, 4, 3],
- [1, 2, 2],
- [6, 0, 0],
- [0, 1, 1],
- [4, 3, 1]
-
假设进程P1请求资源[1, 0, 2]。以下是银行家算法的具体步骤:
-
检查请求是否合法:
- 请求量不超过需求:
Request <= Need
,[1, 0, 2] <= [1, 2, 2] - 请求量不超过可用资源:
Request <= Available
,[1, 0, 2] <= [3, 3, 2]
- 请求量不超过需求:
-
试探性分配:
- 更新
Available
:Available
= [3, 3, 2] - [1, 0, 2] = [2, 3, 0] - 更新
Allocation
:Allocation[1]
= [2, 0, 0] + [1, 0, 2] = [3, 0, 2] - 更新
Need
:Need[1]
= [1, 2, 2] - [1, 0, 2] = [0, 2, 0]
- 更新
-
安全性检查:
- 尝试找到一个安全序列,使得每个进程在获得资源后能够完成并释放资源。
- 安全序列:P1 -> P3 -> P4 -> P0 -> P2
-
正式分配资源:如果系统处于安全状态,则正式分配资源;否则,恢复原始状态,拒绝请求。
-
五、银行家算法代码实现
下面是C++实现银行家算法
-
#include <iostream> #include <vector> using namespace std; class BankersAlgorithm { private: int n; // 进程数量 int m; // 资源类型数量 vector<int> available; // 当前可用的各类资源数目 vector<vector<int>> max; // 每个进程对各类资源的最大需求 vector<vector<int>> allocation; // 每个进程当前已分配到的各类资源数目 vector<vector<int>> need; // 每个进程尚需的各类资源数目 public: BankersAlgorithm(int num_processes, int num_resources, vector<int> avail, vector<vector<int>> max_matrix, vector<vector<int>> alloc_matrix) { n = num_processes; m = num_resources; available = avail; max = max_matrix; allocation = alloc_matrix; need.resize(n, vector<int>(m)); calculateNeed(); } void calculateNeed() { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { need[i][j] = max[i][j] - allocation[i][j]; } } } bool isSafeState() { vector<int> work = available; vector<bool> finish(n, false); vector<int> safeSequence; while (safeSequence.size() < n) { bool found = false; for (int i = 0; i < n; i++) { if (!finish[i]) { bool canProceed = true; for (int j = 0; j < m; j++) { if (need[i][j] > work[j]) { canProceed = false; break; } } if (canProceed) { for (int k = 0; k < m; k++) { work[k] += allocation[i][k]; } safeSequence.push_back(i); finish[i] = true; found = true; } } } if (!found) { return false; } } return true; } bool requestResources(int process_id, vector<int> request) { for (int i = 0; i < m; i++) { if (request[i] > need[process_id][i] || request[i] > available[i]) { return false; // 请求不合法 } } // 试探性分配资源 for (int i = 0; i < m; i++) { available[i] -= request[i]; allocation[process_id][i] += request[i]; need[process_id][i] -= request[i]; } // 检查系统是否处于安全状态 if (isSafeState()) { return true; // 请求被批准 } else { // 恢复原状态 for (int i = 0; i < m; i++) { available[i] += request[i]; allocation[process_id][i] -= request[i]; need[process_id][i] += request[i]; } return false; // 请求被拒绝 } } }; int main() { int n = 5; // 进程数量 int m = 3; // 资源类型数量 vector<int> available = {3, 3, 2}; // 当前可用的各类资源数目 vector<vector<int>> max = { // 每个进程对各类资源的最大需求 {7, 5, 3}, {3, 2, 2}, {9, 0, 2}, {2, 2, 2}, {4, 3, 3} }; vector<vector<int>> allocation = { // 每个进程当前已分配到的各类资源数目 {0, 1, 0}, {2, 0, 0}, {3, 0, 2}, {2, 1, 1}, {0, 0, 2} }; BankersAlgorithm ba(n, m, available, max, allocation); int process_id = 1; // 请求资源的进程ID vector<int> request = {1, 0, 2}; // 请求的资源向量 if (ba.requestResources(process_id, request)) { cout << "资源请求被批准。系统处于安全状态。" << endl; } else { cout << "资源请求被拒绝。系统将进入不安全状态。" << endl; } return 0; }
详细解释
-
初始化系统状态:
available
:表示系统当前可用的各类资源数量。max
:每个进程对各类资源的最大需求。allocation
:每个进程当前已分配的各类资源数量。need
:每个进程尚需的各类资源数量,通过max
和allocation
矩阵计算得出。
-
计算
need
矩阵:- 使用
calculateNeed
函数,通过max
和allocation
矩阵计算出need
矩阵。
- 使用
-
安全性检查:
- 使用
isSafeState
函数检查系统是否处于安全状态。 - 初始化
work
数组为当前可用资源。 - 使用
finish
数组记录每个进程是否完成。 - 找到一个尚未完成且可以得到所有所需资源的进程,假设其完成并释放资源,更新
work
数组和finish
数组。 - 重复上述步骤,直到找到安全序列或无法找到满足条件的进程。
- 使用
-
处理资源请求:
- 使用
requestResources
函数处理资源请求。 - 检查请求是否合法,即请求量不超过进程的最大需求和系统的可用资源。
- 试探性分配资源并更新系统状态。
- 调用
isSafeState
函数检查系统是否处于安全状态。如果安全,正式分配资源;否则,恢复原状态,拒绝请求。
- 使用