小知识: 资源分配拒绝(DFS实现)

308 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

资源分配拒绝算法,又称银行家算法,用于在一种理论的情况下实现死锁的避免。

具体方法为,假设已知当前各个进程算需要的最大资源需求,当且已经分配给它的数量,以及资源总数量。需要找出是否有办法让所有的进程都完成运行,而不会死锁。(实际使用是求在是否能分配资源给进程,不过我们可以把已经分配的情况看作初始情况,这样就是前面说的过程)。

假设有方法可以满足要求的话,显然的是,进程运行完成的顺序会是一个排列。 而排列是典型的dfs搜索问题。

我们假设我们的这些数据都是用numpy储存的,这样后续的条件检测好处理。(比如对于每个进程能否顺利运行,实际上是可用的资源向量和仍需要的资源向量的比较,而这些已分配,未分配之类的矩阵互相直接也是有算术关系的,借助numpy可以快速的求值)。 具体到代码上是下面这样

def get_random_allocation(available, claim, kind, pid):
    alloc, = np.random.randint(0, min(available[kind], claim[pid][kind]) + 1, size=1)
    available[kind] -= alloc
    return alloc
# 生成初始状态
def gen_init_state(kind, p_count):
    resource = np.random.randint(3, 15, size=kind)
    available = np.array(resource)
    claim = np.asarray([np.random.randint(0, i + 1, size=p_count) for i in resource]).T
    allocation = np.asarray([
        get_random_allocation(available, claim, kind, pid)
        for pid in range(count)
        for kind in range(kinds)
    ]).reshape(count, kinds)
    return resource, available, claim, allocation
# 求解可行的分配序列
finished = [False] * 4 
temp = [0] * 4 
result = [] 
def get_array(loc, available, count): 
    if all(finished): 
        result.append(temp.copy())
    else:
        for pid in range(count): 
            if not finished[pid] and (need[pid] <= available).all(): 
                finished[pid] = True 
                temp[loc] = pid 
                get_array(loc + 1, available + allocation[pid], count) 
                finished[pid] = False

为了能够正常的演示,我们编写了一个随机生成初始状态的函数,先前也说过,分配需求之后的效果和初始状态去求可行序列,本质是等价的。

资源的分配也是尽量的随机,以模拟各种可能的状态。dfs基本上与dfs求排列一致,不过在搜索过程我们加了剪枝操作,目的是避免不必要的搜索。由于每个进程在运行完成之后,它占用的资源会被交换给系统,因此我们要把可用资源数量做修改,用于下一次检测。

至此,我们完成了银行家算法的实现。