银行家算法技术总结与性能优化方案

一、算法基础概述

1.1 核心定义

银行家算法 是操作系统中经典的死锁避免算法,通过资源请求前置校验、安全状态模拟推演,提前拒绝会导致系统进入不安全状态的资源分配,从源头规避死锁。

1.2 核心数据结构

  • Available:一维数组,记录系统当前空闲可用资源
  • Max:二维矩阵,记录每个进程的最大资源需求
  • Allocation:二维矩阵,记录每个进程已分配资源
  • Need:二维矩阵,记录进程剩余资源需求,计算公式:Need=Max−AllocationNeed = Max - AllocationNeed=MaxAllocation
  • Work:临时资源数组,安全检测中模拟系统空闲资源
  • Finish:标记数组,标识进程是否可正常执行完成

1.3 执行流程

  1. 校验进程本次资源请求 RequestRequestRequest 是否大于自身 NeedNeedNeed,超出则直接拒绝
  2. 校验 RequestRequestRequest 是否大于系统当前 AvailableAvailableAvailable,资源不足则进程等待
  3. 执行试探性资源分配,临时更新各类资源数据
  4. 运行安全状态检测,判断是否存在合法安全序列
  5. 安全则正式分配资源,不安全则撤销分配并拒绝请求

1.4 银行家算法执行步骤

步骤1:进程发出资源请求

进程 PiP_iPi 向系统发起资源请求,请求向量记为 RequestiRequest_iRequesti

步骤2:合法性检查(请求预校验)

对本次请求做两次基础校验,任何一项不满足都不进入后续流程:

  • 检查是否超过自身最大需求
    Requesti≤NeediRequest_i \le Need_iRequestiNeedi
    不满足:说明请求资源超过进程的最大需求,判定为非法请求,直接拒绝。
  • 检查系统当前可用资源是否足够
    Requesti≤AvailableRequest_i \le AvailableRequestiAvailable
    不满足:当前空闲资源不足,进程需要等待。
步骤3:试探分配资源(假设分配)

如果上述两项检查都通过,系统临时修改资源数据,模拟分配资源,不做实际分配:
Available=Available−RequestiAvailable = Available - Request_iAvailable=AvailableRequesti
Allocationi=Allocationi+RequestiAllocation_i = Allocation_i + Request_iAllocationi=Allocationi+Requesti
Needi=Needi−RequestiNeed_i = Need_i - Request_iNeedi=NeediRequesti

步骤4:安全状态检测

系统需要判断:经过试探分配后,系统是否仍然处于安全状态,即是否存在安全序列:

  1. 初始化
    • Work=AvailableWork = AvailableWork=Available(将当前可用资源赋值给临时变量)
    • 初始化 Finish 数组,所有元素设为 false(标记进程是否可执行完成)
  2. 循环查找可执行进程
    遍历所有进程,寻找满足以下两个条件的进程 (P_j):
    • Finish[j]=falseFinish[j] = falseFinish[j]=false(进程尚未标记为可完成)
    • Needj≤WorkNeed_j \le WorkNeedjWork(进程的剩余需求 ≤ 当前可用资源)
  3. 模拟进程执行并释放资源
    找到满足条件的进程后,模拟其执行完成并释放所有资源:
    Work=Work+AllocationjWork = Work + Allocation_jWork=Work+Allocationj
    同时标记 Finish[j]=trueFinish[j] = trueFinish[j]=true
  4. 判断结果
    • 若遍历结束后,所有 Finish 元素均为 true:存在安全序列,系统安全 → 正式分配资源
    • 若存在 false:系统不安全 → 撤销试探分配,进程等待

二、算法优缺点分析

2.1 优点

  • 主动规避死锁,无需事后检测与解除,系统稳定性强
  • 支持资源动态分配,相比静态一次性分配,资源利用率更高
  • 逻辑规则标准化,易于理解、教学与小型场景落地

2.2 缺点

  • 前置条件严苛,必须提前精准预估所有进程的最大资源需求,通用场景难以实现
  • 算法假设进程连续执行、进程与资源数量固定,与真实动态运行场景不符
  • 每次资源请求都需全量遍历检测,进程与资源规模变大后,计算性能开销显著提升
  • 为保障系统安全,部分合法资源请求也会被拒绝,易造成进程长时间阻塞等待
  • 无法应对进程异常退出、资源故障等突发运行场景

三、核心性能瓶颈

  • 安全检测阶段全量遍历所有进程,时间复杂度高
  • 试探分配时频繁深拷贝资源矩阵,内存与数据拷贝开销大
  • 安全序列采用暴力检索,无剪枝逻辑,检索效率低
  • 资源变动时执行全量重检测,检测粒度粗、冗余计算多

四、性能优化方案

4.1 安全检测逻辑优化

  • 进程候选集剪枝:仅将满足 Need≤WorkNeed \le WorkNeedWork 的进程纳入遍历范围,减少循环次数
  • 贪心排序检索:优先选择剩余资源需求最小的进程推演,加快安全序列查找
  • 历史序列缓存:资源状态无大幅变动时,复用历史有效安全序列
  • 增量检测机制:仅对发起请求及受影响的进程做局部校验,替代全局全量检测

4.2 数据结构与内存优化

  • 原地回滚替代深拷贝:试探分配直接修改原数据,检测失败后通过加减法回滚数据,消除拷贝开销
  • 向量向量化运算:使用批量向量对比替代多层循环,提升资源校验速度
  • 数据分层存储:静态数据与动态数据分离存储,提升CPU缓存命中率

4.3 调度策略优化

  • 合并资源请求:将进程多次小额请求合并为单次请求,减少安全检测触发次数
  • 分级检测机制:设置快速预校验+分级检测,低风险请求简化检测逻辑
  • 异步后台检测:临时分配资源,后台异步执行安全校验,异常时再回收资源(适用于可容忍低死锁风险场景)

4.4 业务与运行适配优化

  • 动态修正最大需求:根据进程历史运行数据,动态更新 MaxMaxMax 数值,适配真实业务
  • 进程资源分组管理:按业务划分进程与资源组,组内独立执行算法,支持并行检测
  • 定时清理无效进程:及时销毁已结束进程,缩减遍历范围

五、配套死锁处理方案

5.1 主流死锁处理方式对比

  • 死锁预防:破坏死锁四大必要条件,实现简单,资源利用率低
  • 死锁避免(银行家算法):事前预判规避死锁,适用于封闭小型系统
  • 死锁检测+解除:允许进入死锁状态,事后发现并修复,通用系统主流方案

5.2 死锁检测算法

沿用资源矩阵模型,遍历模拟进程执行,最终无法完成的进程集合即为死锁进程。

5.3 死锁解除策略

  • 资源剥夺:强行回收死锁进程资源,分配至其他进程,业务影响最小
  • 进程回滚:基于检查点将进程回退至正常状态,适用于事务型系统
  • 终止进程:结束死锁进程并回收资源,实现最简单,存在任务丢失风险
  • 系统重启:兜底方案,极端死锁场景下使用

六、代码实现示例

6.1 银行家算法完整代码

import copy

def is_safe(available, max_need, allocation, need):
    n = len(need)
    m = len(available)
    work = copy.deepcopy(available)
    finish = [False] * n
    safe_seq = []

    while len(safe_seq) < n:
        found = False
        for i in range(n):
            if not finish[i]:
                flag = True
                for j in range(m):
                    if need[i][j] > work[j]:
                        flag = False
                        break
                if flag:
                    for j in range(m):
                        work[j] += allocation[i][j]
                    finish[i] = True
                    safe_seq.append(f"P{i}")
                    found = True
        if not found:
            return False, []
    return True, safe_seq

def bank_request(process_id, request, available, max_need, allocation, need):
    n = len(need)
    m = len(available)

    for j in range(m):
        if request[j] > need[process_id][j]:
            print(f"进程P{process_id} 请求超出最大需求,拒绝分配")
            return available, max_need, allocation, need

    for j in range(m):
        if request[j] > available[j]:
            print(f"系统资源不足,进程P{process_id} 等待")
            return available, max_need, allocation, need

    temp_available = copy.deepcopy(available)
    temp_allocation = copy.deepcopy(allocation)
    temp_need = copy.deepcopy(need)

    for j in range(m):
        temp_available[j] -= request[j]
        temp_allocation[process_id][j] += request[j]
        temp_need[process_id][j] -= request[j]

    safe, seq = is_safe(temp_available, max_need, temp_allocation, temp_need)
    if safe:
        print(f"分配成功,安全序列:{seq}")
        return temp_available, max_need, temp_allocation, temp_need
    else:
        print("分配后系统不安全,拒绝请求")
        return available, max_need, allocation, need

if __name__ == "__main__":
    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 = []
    for i in range(len(Max)):
        tmp = []
        for j in range(len(Available)):
            tmp.append(Max[i][j] - Allocation[i][j])
        Need.append(tmp)

    print("初始可用资源:", Available)
    Available, Max, Allocation, Need = bank_request(1, [1, 0, 2], Available, Max, Allocation, Need)
    Available, Max, Allocation, Need = bank_request(4, [3, 3, 0], Available, Max, Allocation, Need)

6.2 死锁检测与解除代码

import copy

def deadlock_detect(available, allocation, need):
    n = len(allocation)
    m = len(available)
    work = copy.deepcopy(available)
    finish = [False] * n

    while True:
        find = False
        for i in range(n):
            if not finish[i]:
                satisfy = True
                for j in range(m):
                    if need[i][j] > work[j]:
                        satisfy = False
                        break
                if satisfy:
                    for j in range(m):
                        work[j] += allocation[i][j]
                    finish[i] = True
                    find = True
        if not find:
            break
    deadlock_proc = [i for i in range(n) if not finish[i]]
    return len(deadlock_proc) > 0, deadlock_proc

def resolve_deadlock(dead_procs, allocation, available):
    if not dead_procs:
        return available, allocation
    kill_pid = dead_procs[0]
    print(f"终止进程P{kill_pid},回收资源")
    for idx in range(len(available)):
        available[idx] += allocation[kill_pid][idx]
        allocation[kill_pid] = 0
    return available, allocation

if __name__ == "__main__":
    Available = [1, 0, 2]
    Allocation = [[0, 1, 0],[2, 0, 0],[3, 0, 2],[2, 1, 1],[0, 0, 2]]
    Need = [[7, 4, 3],[1, 2, 2],[6, 0, 0],[0, 1, 1],[4, 3, 1]]

    has_deadlock, dead_list = deadlock_detect(Available, Allocation, Need)
    if has_deadlock:
        print(f"检测到死锁进程:{dead_list}")
        Available, Allocation = resolve_deadlock(dead_list, Allocation, Available)
        new_lock, new_list = deadlock_detect(Available, Allocation, Need)
        print("解除后是否存在死锁:", new_lock)

七、应用场景

7.1 适用场景

  • 嵌入式/实时工控系统:设备功能固定,进程与资源需求可提前预估
  • 小型专用服务器、单机批处理系统:进程数量稳定,无频繁动态创建销毁
  • 教学仿真平台:用于操作系统原理教学、算法实验演示
  • 高可靠专用设备:医疗仪器、金融终端等零死锁要求的封闭系统

7.2 不适用场景

  • 通用大型操作系统:进程动态变化,资源需求无法预判
  • 高并发互联网、分布式系统:节点与请求海量,调度复杂
  • 移动端、消费级应用软件:后台任务随机,资源管控难度大
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐