项目名称:银行家算法实现

项目背景

银行家算法(Banker's Algorithm)是一种用于避免死锁的算法,主要用于资源分配系统中,确保系统在分配资源后仍然处于安全状态。该算法由艾兹赫尔·狄克斯特拉(Edsger Dijkstra)提出,最初用于银行贷款系统,因此得名“银行家算法”。

在操作系统中,资源分配和管理是核心问题,特别是在多进程并发执行的环境下,需要避免由于资源竞争引发的死锁。银行家算法通过对进程资源需求的动态分析,在分配资源前进行“安全性检查”,从而保证系统不会进入死锁状态。


项目目标
  1. 功能实现
    • 使用C++实现银行家算法,支持动态资源分配与释放。
  2. 代码注释与解读
    • 提供详细的注释与算法流程解读,便于学习与扩展。
  3. 项目结构
    • 模块化设计,包含资源初始化、分配、安全性检查等功能。
  4. 测试与验证
    • 设计多组测试用例,验证算法的正确性与鲁棒性。

银行家算法的基本原理

核心概念
  1. 资源类型: 系统中有多种类型的资源,例如CPU、内存、I/O设备等。
  2. 矩阵描述
    • Available:系统当前可用资源数量向量。
    • Max:每个进程对各类资源的最大需求矩阵。
    • Allocation:当前已经分配给各进程的资源数量矩阵。
    • Need:每个进程尚需的资源数量矩阵,Need[i][j] = Max[i][j] - Allocation[i][j]
安全性检查

银行家算法在分配资源之前,通过“安全性算法”预测分配后的系统是否处于安全状态。系统安全状态的定义是:存在一个进程执行顺序,使得所有进程可以在有限时间内完成并释放资源。

资源分配流程
  1. 检查请求是否合法(请求量不能超过进程声明的最大需求)。
  2. 判断资源是否足够满足请求(请求量不能超过系统当前可用资源量)。
  3. 假设分配资源,检查分配后的系统是否安全:
    • 如果安全,则实际分配资源。
    • 如果不安全,拒绝分配,保持系统稳定。

项目结构

模块化设计如下:

  1. 主模块:程序入口,负责用户交互和调用核心函数。
  2. 数据初始化模块:定义资源矩阵,初始化进程信息。
  3. 资源分配模块:根据进程请求更新资源分配状态。
  4. 安全性检查模块:判断当前资源分配是否安全。
  5. 测试模块:包含不同场景下的测试用例。

C++实现

以下是银行家算法的完整实现代码:

#include <iostream>
#include <vector>
using namespace std;

// 定义全局变量
int numProcesses, numResources; // 进程数和资源种类数
vector<int> Available;          // 当前可用资源
vector<vector<int>> Max;        // 每个进程的最大需求
vector<vector<int>> Allocation; // 已分配资源
vector<vector<int>> Need;       // 尚需资源

// 安全性检查函数
bool isSafe() {
    vector<int> Work = Available;   // 可用资源向量
    vector<bool> Finish(numProcesses, false); // 记录进程是否完成
    vector<int> safeSequence;       // 安全序列

    for (int count = 0; count < numProcesses; ++count) {
        bool found = false;
        for (int i = 0; i < numProcesses; ++i) {
            if (!Finish[i]) {
                bool canAllocate = true;
                for (int j = 0; j < numResources; ++j) {
                    if (Need[i][j] > Work[j]) { // 当前资源不足
                        canAllocate = false;
                        break;
                    }
                }
                if (canAllocate) {
                    // 假设分配资源
                    for (int j = 0; j < numResources; ++j) {
                        Work[j] += Allocation[i][j];
                    }
                    safeSequence.push_back(i); // 记录进程顺序
                    Finish[i] = true;          // 标记完成
                    found = true;
                }
            }
        }
        if (!found) { // 如果找不到可以分配的进程
            cout << "系统处于不安全状态!" << endl;
            return false;
        }
    }

    cout << "系统处于安全状态,安全序列为:";
    for (int i : safeSequence) {
        cout << "P" << i << " ";
    }
    cout << endl;
    return true;
}

// 资源请求函数
void requestResource(int processID, vector<int> request) {
    cout << "进程 P" << processID << " 请求资源:";
    for (int r : request) {
        cout << r << " ";
    }
    cout << endl;

    // 检查请求是否合法
    for (int i = 0; i < numResources; ++i) {
        if (request[i] > Need[processID][i]) {
            cout << "请求超过进程的最大需求!" << endl;
            return;
        }
        if (request[i] > Available[i]) {
            cout << "请求超过系统当前可用资源!" << endl;
            return;
        }
    }

    // 假设分配资源
    for (int i = 0; i < numResources; ++i) {
        Available[i] -= request[i];
        Allocation[processID][i] += request[i];
        Need[processID][i] -= request[i];
    }

    // 安全性检查
    if (isSafe()) {
        cout << "资源分配成功!" << endl;
    } else {
        // 回滚资源分配
        cout << "分配后系统处于不安全状态,拒绝分配!" << endl;
        for (int i = 0; i < numResources; ++i) {
            Available[i] += request[i];
            Allocation[processID][i] -= request[i];
            Need[processID][i] += request[i];
        }
    }
}

int main() {
    // 输入系统资源信息
    cout << "请输入进程数和资源种类数: ";
    cin >> numProcesses >> numResources;

    Available.resize(numResources);
    Max.resize(numProcesses, vector<int>(numResources));
    Allocation.resize(numProcesses, vector<int>(numResources, 0));
    Need.resize(numProcesses, vector<int>(numResources));

    cout << "请输入系统可用资源向量: ";
    for (int i = 0; i < numResources; ++i) {
        cin >> Available[i];
    }

    cout << "请输入每个进程的最大需求矩阵: " << endl;
    for (int i = 0; i < numProcesses; ++i) {
        for (int j = 0; j < numResources; ++j) {
            cin >> Max[i][j];
            Need[i][j] = Max[i][j]; // 初始化Need矩阵
        }
    }

    // 模拟资源请求
    while (true) {
        int processID;
        vector<int> request(numResources);

        cout << "\n请输入请求资源的进程ID (-1退出): ";
        cin >> processID;
        if (processID == -1) break;

        cout << "请输入请求资源向量: ";
        for (int i = 0; i < numResources; ++i) {
            cin >> request[i];
        }

        requestResource(processID, request);
    }

    return 0;
}

代码解读

  1. 数据结构

    • 使用二维向量存储 MaxAllocationNeed 矩阵。
    • 使用一维向量存储 AvailableWork
  2. 核心逻辑

    • 安全性检查:逐进程模拟分配,确保系统最终处于安全状态。
    • 资源请求处理:先验证请求的合法性,再尝试分配并检查安全性。
  3. 用户交互

    • 用户动态输入资源请求,系统实时判断是否可以分配。

测试用例

测试数据
  1. 系统可用资源:[3, 3, 2]
  2. 最大需求矩阵
P0: [7, 5, 3]
P1: [3, 2, 2]
P2: [9, 0, 2]
P3: [2, 2, 2]
P4: [4, 3, 3]

当前分配矩阵

P0: [0, 1, 0]
P1: [2, 0, 0]
P2: [3, 0, 2]
P3: [2, 1, 1]
P4: [0, 0, 2]
测试场景
  1. 合法请求:进程 P1 请求资源 [1, 0, 2]
  2. 非法请求:进程 P2 请求资源 [6, 0, 2](超出可用资源)。

总结与优化方向

  1. 优点

    • 确保资源分配安全性,避免死锁。
    • 易于理解和实现,适合小规模系统。
  2. 缺点

    • 时间复杂度较高,安全性检查需遍历所有进程。
    • 适用场景有限,不适合高并发大规模资源管理。
  3. 优化方向

    • 引入多线程并行检查,提高安全性判断效率。
    • 结合实际场景设计更灵活的资源分配策略(如优先级)。

更多推荐