Python实现哲学家就餐问题实例代码
作者:Snippers 发布时间:2022-09-20 14:10:49
哲学家就餐问题:
哲学家就餐问题是典型的同步问题,该问题描述的是五个哲学家共用一张圆桌,分别坐在五张椅子上,在圆桌上有五个盘子和五个叉子(如下图),他们的生活方式是交替的进行思考和进餐,思考时不能用餐,用餐时不能思考。平时,一个哲学家进行思考,饥饿时便试图用餐,只有在他同时拿到他的盘子左右两边的两个叉子时才能进餐。进餐完毕后,他会放下叉子继续思考。请写出代码来解决如上的哲学家就餐问题,要求代码返回“当每个哲学家分别需要进食 n 次”时这五位哲学家具体的行为记录。
测试用例:
输入:n = 1 (1<=n<=60,n 表示每个哲学家需要进餐的次数。)
预期输出:
[[4,2,1],[4,1,1],[0,1,1],[2,2,1],[2,1,1],[2,0,3],[2,1,2],[2,2,2],[4,0,3],[4,1,2],[0,2,1],[4,2,2],[3,2,1],[3,1,1],[0,0,3],[0,1,2],[0,2,2],[1,2,1],[1,1,1],[3,0,3],[3,1,2],[3,2,2],[1,0,3],[1,1,2],[1,2,2]]
思路:
输出列表中的每一个子列表描述了某个哲学家的具体行为,它的格式如下:
output[i] = [a, b, c] (3 个整数)
a 哲学家编号。
b 指定叉子:{1 : 左边, 2 : 右边}.
c 指定行为:{1 : 拿起, 2 : 放下, 3 : 吃面}。
如 [4,2,1] 表示 4 号哲学家拿起了右边的叉子。所有自列表组合起来,就完整描述了“当每个哲学家分别需要进食 n 次”时这五位哲学家具体的行为记录。
代码实现
import queue
import threading
import time
import random
class CountDownLatch:
def __init__(self, count):
self.count = count
self.condition = threading.Condition()
def wait(self):
try:
self.condition.acquire()
while self.count > 0:
self.condition.wait()
finally:
self.condition.release()
def count_down(self):
try:
self.condition.acquire()
self.count -= 1
self.condition.notifyAll()
finally:
self.condition.release()
class DiningPhilosophers(threading.Thread):
def __init__(self, philosopher_number, left_fork, right_fork, operate_queue, count_latch):
super().__init__()
self.philosopher_number = philosopher_number
self.left_fork = left_fork
self.right_fork = right_fork
self.operate_queue = operate_queue
self.count_latch = count_latch
def eat(self):
time.sleep(0.01)
self.operate_queue.put([self.philosopher_number, 0, 3])
def think(self):
time.sleep(random.random())
def pick_left_fork(self):
self.operate_queue.put([self.philosopher_number, 1, 1])
def pick_right_fork(self):
self.operate_queue.put([self.philosopher_number, 2, 1])
def put_left_fork(self):
self.left_fork.release()
self.operate_queue.put([self.philosopher_number, 1, 2])
def put_right_fork(self):
self.right_fork.release()
self.operate_queue.put([self.philosopher_number, 2, 2])
def run(self):
while True:
left = self.left_fork.acquire(blocking=False)
right = self.right_fork.acquire(blocking=False)
if left and right:
self.pick_left_fork()
self.pick_right_fork()
self.eat()
self.put_left_fork()
self.put_right_fork()
break
elif left and not right:
self.left_fork.release()
elif right and not left:
self.right_fork.release()
else:
time.sleep(0.01)
print(str(self.philosopher_number) + ' count_down')
self.count_latch.count_down()
if __name__ == '__main__':
operate_queue = queue.Queue()
fork1 = threading.Lock()
fork2 = threading.Lock()
fork3 = threading.Lock()
fork4 = threading.Lock()
fork5 = threading.Lock()
n = 1
latch = CountDownLatch(5 * n)
for _ in range(n):
philosopher0 = DiningPhilosophers(0, fork5, fork1, operate_queue, latch)
philosopher0.start()
philosopher1 = DiningPhilosophers(1, fork1, fork2, operate_queue, latch)
philosopher1.start()
philosopher2 = DiningPhilosophers(2, fork2, fork3, operate_queue, latch)
philosopher2.start()
philosopher3 = DiningPhilosophers(3, fork3, fork4, operate_queue, latch)
philosopher3.start()
philosopher4 = DiningPhilosophers(4, fork4, fork5, operate_queue, latch)
philosopher4.start()
latch.wait()
queue_list = []
for i in range(5 * 5 * n):
queue_list.append(operate_queue.get())
print(queue_list)
来源:https://blog.csdn.net/Snippers/article/details/109563341
猜你喜欢
- asp如何实现当前月份距离以前某个时间的月份数 如今天是2011年1月份,我想知道离2010年3月,计算这中间一共是几个月 最佳答案 <
- 读《论语》,子张十九,子夏曰:博学而笃志,切问而近思,仁在其中矣。 博学:架构需要广度,要尽量多学习各方面的知识。笃志:除了广度,架构师还需
- replace 方法返回根据正则表达式进行文字替换后的字符串的复制。stringObj.replace(rgExp, replaceText
- Limit语法:SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offsetL
- 面是我下载页面down.php 的php代码 现在我发现,用迅雷,谷歌浏览器直接打开,就能输出下载文件,一点不起防盗链作用。&nb
- readlines的帮助信息>>> fr=open('readme.txt')>>> h
- 网站能切换几套CSS风格早已不是什么新鲜事了。大家也都知道怎么去弄。早上发现一个有意思得站点 http://www.leemunroe.co
- 在了解XHTML代码规范后,我们就要进行CSS布局。首先先介绍一些CSS的入门知识。如果你已经很熟悉了,可以跳过这一节。CSS是Cascad
- 看下面的Java代码,目的是为了当i是3的时候,就不做输出,直接跳到下一个循环。int i = 0; 
- 这篇是Nicholas讨论如果防止脚本失控的第二篇,主要讨论了如何重构嵌套循环、递归,以及那些在函数内部同时执行很多子操作的函数。基本的思想
- 根据Django官方文档介绍:A one-to-one relationship. Conceptually, this is simila
- 一般事件事件浏览器支持描述onClickHTML: 2 | 3 | 3.2 |
- 如何在网上查找链接? 见下:findlinks.html<html><head>
- 垃圾评论,垃圾留言,人见人憎,用了验证码,效果也好不到哪里去,还影响用户体验。有的网站甚至不惜牺牲用户体验,而构造强悍的惨不忍睹的超级验证码
- 这个话题是应腾讯ISD同仁之邀在WebReBuild三周年交流会上做的主题分享。由于临场等原因有些问题当时没有讲明白,回来后按原有思路形成了
- iframe的防插与强插(一)中介绍了“市面上”能见到的两种防御被第三方网站iframe的方法,以及相应的变态突破方法。貌似把“受害人”逼上
- 我是在做行人检测中需要将一段视频变为图片数据集,然后想将视频每秒钟的图片提取出来。语言:python所需要的库:cv2,numpy (自行安
- 准备软件:1. J2SDK(1.5.0): jdk-1_5_0-linux-i586-rpm.bin2. Apache(2.0.53): h
- Doug Bowman,Google的Visual Design Lead离职了,一封带有感 * 彩的离职信惹发了大家不少的讨论。甚至还有人用
- __init__()方法意义重大的原因有两个。第一个原因是在对象生命周期中初始化是最重要的一步;每个对象必须正确初始化后才能正常工作。第二个