1、实验目的

加深了解死锁概念,体会产生死锁的原因,掌握避免死锁的具体实施方法。2、实验内容

编写一个系统动态分配资源的模拟程序,采用银行家算法有效地避免死锁的发生。要求程序能够在进程提出资源申请后判断系统是否处于安全状态,如果安全则打印资源分配表和安全序列:如果不安全则输出不能分配的提示。

3、算法设计

数据结构:

变量名

类型

注释

available

一维数组

表示每种资源可用的数量

max

二维数组

表示每个进程需要的最大资源数量

allocation

二维数组

表示每个进程已经分配的资源数量

need

二维数组

表示每个进程还需要的资源数量

work

一维数组

表示每个进程可用的资源数量

finish

一维数组

表示每个进程是否可以完成执行

n

整数

表示系统中进程的数量

m

整数

表示系统中资源的种类数量

本程序实现了银行家算法的基本逻辑,用于模拟资源管理和进程调度。用户可以通过输入请求来模拟不同的情况,以验证系统的安全性和资源分配策略。下面是银行家算法的设计说明:

(1)导入测试数据( loadTestData 函数):首先,代码导入了测试数据,包括可用资源向量( available )、最大需求矩阵( max_table )、分配矩阵( allocation )。这些数据模拟了系统中各个进程对资源的需求和分配情况。

(2)输出表格( printTable 函数):这个函数用于在控制台输出进程的最大需求、已分配资源、尚需资源情况,以及当前可用资源。这有助于用户了解系统的初始状态。

(3)安全性算法( security 函数):这是银行家算法的核心部分。它模拟了系统的安全性检查,以确保没有死锁的风险。具体步骤如下:

初始化一个布尔数组  finish ,表示每个进程是否完成,初始为全 False 。

进入一个循环,直到所有进程都完成:遍历每个进程,检查是否有未完成的进程,并且该进程的需求资源小于等于当前可用资源(即安全性检查)。如果找到一个满足条件的进程,输出它的标识(如"P0"),将其持有的资源释放给系统( work += allocation[i] ),并将该进程标记为已完成( finish[i] = True )。如果没有找到可执行的进程,返回 False ,表示系统处于不安全状态。

当循环结束后,返回 True ,表示系统是安全的。

(4)主函数( main 函数):这是程序的入口点。首先,它输出初始的资源分配情况,然后进入一个循环,用户可以输入进程的资源请求。主要步骤如下:

用户输入进程标识和资源请求,例如"P1, 1 0 1"。

程序判断资源请求的合法性,包括请求不得超过最大需求( max_table )、请求不得超过尚需资源( need )。

如果请求合法,程序尝试模拟资源分配,减少可用资源( available )、增加分配资源( allocation )、减少尚需资源( need )。

然后,程序调用 security 函数来检查系统是否处于安全状态。如果安全,系统会继续运行,输出新的资源状态;如果不安全,请求将被拒绝,资源状态回滚。

用户可以反复输入请求,直到系统进入不安全状态,或者用户终止程序。

4、运行与测试

图 6根据初始化后的系统数据打印资源分配表

图 7请求资源分配

图 8请求资源分配失败

模拟进程提出资源申请,系统进行安全状态检查,若安全则为其分配资源并更新资源分配表,若不安全或者不合法则输出相应提示

5、总结与心得

通过本次实验,我加深“银行家算法”核心思想的理解,就是在资源分配之前判断本次分配是否会导致系统进入不安全状态,根据这个判断决定是否同意资源分配请求。并且不安全状态未必就是发生了死锁,但发生死锁时一定是在不安全状态。

import numpy as np

def security(work, need, allocation):
    """安全性算法"""
    n = need.shape[0]   #读取矩阵第一维度的长度
    finish = np.array([False] * n, dtype=bool) #系统是否有足够的资源分配给进程使之运行完成,初始化false
    while not(finish.all()):  # 当存在未完成的进程时循环执行以下操作
        flag = False
        for i in range(n):
            if not finish[i] and (need[i] <= work).all():    # 如果进程未完成且当前可用资源满足进程的需求
                print("P{}".format(i), end=' -> ')
                flag = True
                work += allocation[i]   # 将进程持有的资源释放
                finish[i] = True        # 将该进程标记为已完成
                break
        if not flag:
            return False
    print()
    return True

def printTable(available, max_table, allocation, need):
    """输出表格"""
    print("=="*30)
    print("进程\tMax\tAllo\tNeed")
    for i in range(5):
        print("P{}\t{}\t{}\t{}".format(
            i, max_table[i], allocation[i], need[i]))
    print("当前剩余资源:", available)

def loadTestData():
    """导入测试数据"""
    return (np.array([10, 5, 7], dtype=int),
            np.array([[7, 5, 3],
                      [3, 2, 2],
                      [9, 0, 2],
                      [2, 2, 2],
                      [4, 3, 3]], dtype=int),
            np.array([[0, 1, 0],
                      [2, 0, 0],
                      [3, 0, 2],
                      [2, 1, 1],
                      [0, 0, 2]], dtype=int))

def main():
    available, max_table, allocation = loadTestData()
    need = max_table - allocation

    # 计算出剩余资源
    for i in allocation:
        available -= i

    printTable(available, max_table, allocation, need)

    while (need != 0).any():
        # 输入进程请求的请求资源
        proc_ind, req = input("输入请求,如:P1, 1 0 1: ").split(',')
        proc_ind = int(proc_ind[1:])
        req = np.array(req.split(), dtype=int)

        # 判断合法性
        if (req > max_table[proc_ind]).any():
            print("[ERROR] 请求资源大于所需资源,请重新输入")
            continue  # 重新输入

        # 判断请求资源是否大于需求资源
        if (req > need[proc_ind]).any():
            print("[ERROR] 请求资源大于所需资源,请重新输入")
            continue  # 重新输入

        # 判断安全性
        else:
            available -= req
            allocation[proc_ind] += req
            need[proc_ind] -= req
            if security(available.copy(), need, allocation):
                printTable(available, max_table, allocation, need)
                continue
            else:
                print("[ERROR] 不安全,不能分配")
                available += req
                allocation[proc_ind] -= req
                need[proc_ind] += req


if __name__ == '__main__':
    main()

 

Logo

鸿蒙生态一站式服务平台。

更多推荐