小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
资源分配拒绝算法,又称银行家算法,用于在一种理论的情况下实现死锁的避免。
具体方法为,假设已知当前各个进程算需要的最大资源需求,当且已经分配给它的数量,以及资源总数量。需要找出是否有办法让所有的进程都完成运行,而不会死锁。(实际使用是求在是否能分配资源给进程,不过我们可以把已经分配的情况看作初始情况,这样就是前面说的过程)。
假设有方法可以满足要求的话,显然的是,进程运行完成的顺序会是一个排列。 而排列是典型的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求排列一致,不过在搜索过程我们加了剪枝操作,目的是避免不必要的搜索。由于每个进程在运行完成之后,它占用的资源会被交换给系统,因此我们要把可用资源数量做修改,用于下一次检测。
至此,我们完成了银行家算法的实现。