【操作系统中银行家算法避免死锁】

文章目录

  • 前言
  • 一、死锁与银行家算法简介
    • 1. 什么是死锁?
    • 2. 银行家算法的由来
  • 二、银行家算法原理与实现步骤
      • 1. 安全性检测算法
      • 2. 银行家算法步骤
  • 三、银行家算法示例(C语言实现)
      • 1. 数据结构设计
      • 2. 安全性检测函数
      • 3. 资源请求与分配
      • 4. 主函数
  • 四、银行家算法的优缺点


前言

在操作系统中,死锁是一种常见的并发问题。当多个进程因竞争资源而相互等待,且无法继续执行时,就会发生死锁。为了避免死锁,银行家算法(Banker’s Algorithm)应运而生。这是一种资源分配和死锁避免的算法,能够在资源请求时动态判断是否会导致系统进入不安全状态,从而决定是否分配资源。


一、死锁与银行家算法简介

1. 什么是死锁?

死锁指的是一组进程因争夺资源而相互等待,导致无法继续执行的现象。产生死锁的四个必要条件:

  • 互斥条件:资源一次只能由一个进程使用。
  • 占有且等待条件:进程已经持有资源,同时等待其他资源。
  • 不可剥夺条件:进程已占有的资源不能被强行剥夺。
  • 循环等待条件:多个进程之间形成资源等待的循环链。

避免死锁的核心思想:在资源分配前,确保系统不会进入不安全状态。

2. 银行家算法的由来

银行家算法由计算机科学家Edsger Dijkstra提出,其灵感来自于银行家在贷款时需评估借款人还款能力:

  • 若贷款不会导致银行破产,则放款;
  • 否则拒绝贷款。

在操作系统中:

  • 进程相当于借款人;
  • 系统资源相当于银行的资金;
  • 资源分配策略决定了是否授予资源,以确保系统始终处于安全状态。

二、银行家算法原理与实现步骤

银行家算法使用以下数据结构:

  • Available:当前可用资源数量。
  • Max:每个进程最大需求量。
  • Allocation:当前已分配给进程的资源。
  • Need:进程仍然需要的资源量,Need = Max - Allocation

1. 安全性检测算法

当资源分配后,算法检查系统是否处于安全状态

  • 计算出当前可用资源 Work = Available
  • 检查是否存在能够满足需求的进程:
    • Need[i] <= Work,则该进程可执行,完成后释放资源;
    • 将释放的资源加入到 Work 中。
  • 若所有进程均可顺利执行完毕,则系统处于安全状态。

2. 银行家算法步骤

  • 请求阶段
    • 检查请求资源是否超过进程的最大需求量。
    • 检查请求资源是否超过当前可用资源。
  • 试探分配
    • 临时分配资源,更新 AvailableAllocationNeed
  • 安全性检测
    • 判断分配后的系统是否处于安全状态。
    • 若安全,则分配成功;否则,回滚。

三、银行家算法示例(C语言实现)

1. 数据结构设计

#include 
#include 

#define P 5  // 进程数
#define R 3  // 资源数

// 全局资源状态
int Available[R] = {3, 3, 2};  // 当前可用资源
int Max[P][R] = {                 // 每个进程最大需求
    {7, 5, 3},
    {3, 2, 2},
    {9, 0, 2},
    {2, 2, 2},
    {4, 3, 3}
};
int Allocation[P][R] = {          // 当前已分配资源
    {0, 1, 0},
    {2, 0, 0},
    {3, 0, 2},
    {2, 1, 1},
    {0, 0, 2}
};
int Need[P][R];                    // 需求资源

2. 安全性检测函数

// 安全性检测
bool isSafe() {
    int work[R];
    bool finish[P] = {false};

    // 初始化工作资源为当前可用资源
    for (int i = 0; i < R; i++) {
        work[i] = Available[i];
    }

    int count = 0;
    while (count < P) {
        bool found = false;

        for (int i = 0; i < P; i++) {
            if (!finish[i]) {
                bool flag = true;

                for (int j = 0; j < R; j++) {
                    if (Need[i][j] > work[j]) {
                        flag = false;
                        break;
                    }
                }

                if (flag) {
                    for (int k = 0; k < R; k++) {
                        work[k] += Allocation[i][k];
                    }
                    finish[i] = true;
                    found = true;
                    count++;
                }
            }
        }

        if (!found) {
            return false;  // 不安全
        }
    }
    return true;  // 安全
}

3. 资源请求与分配

// 资源请求
bool request(int pid, int request[R]) {
    for (int i = 0; i < R; i++) {
        if (request[i] > Need[pid][i] || request[i] > Available[i]) {
            return false;  // 超出需求或资源不足
        }
    }

    // 试探性分配
    for (int i = 0; i < R; i++) {
        Available[i] -= request[i];
        Allocation[pid][i] += request[i];
        Need[pid][i] -= request[i];
    }

    if (isSafe()) {
        return true;  // 安全分配
    } else {
        // 回滚
        for (int i = 0; i < R; i++) {
            Available[i] += request[i];
            Allocation[pid][i] -= request[i];
            Need[pid][i] += request[i];
        }
        return false;  // 不安全,拒绝分配
    }
}

4. 主函数

int main() {
    // 初始化需求矩阵
    for (int i = 0; i < P; i++) {
        for (int j = 0; j < R; j++) {
            Need[i][j] = Max[i][j] - Allocation[i][j];
        }
    }

    int pid = 1;  // 请求进程
    int request[R] = {1, 0, 2};  // 请求的资源数量

    if (request(pid, request)) {
        printf("分配成功!\n");
    } else {
        printf("分配失败!\n");
    }

    return 0;
}

四、银行家算法的优缺点

优点

  • 能有效地避免死锁。
  • 动态分配资源,保证系统安全。

缺点

  • 计算复杂,效率较低。
  • 仅适用于资源需求已知且固定的情况。
  • 不能处理资源抢占。

你可能感兴趣的:(操作系统,算法)