Python实现哲学家就餐问题实例代码


Posted in Python onNovember 09, 2020

哲学家就餐问题:

哲学家就餐问题是典型的同步问题,该问题描述的是五个哲学家共用一张圆桌,分别坐在五张椅子上,在圆桌上有五个盘子和五个叉子(如下图),他们的生活方式是交替的进行思考和进餐,思考时不能用餐,用餐时不能思考。平时,一个哲学家进行思考,饥饿时便试图用餐,只有在他同时拿到他的盘子左右两边的两个叉子时才能进餐。进餐完毕后,他会放下叉子继续思考。请写出代码来解决如上的哲学家就餐问题,要求代码返回“当每个哲学家分别需要进食 n 次”时这五位哲学家具体的行为记录。

Python实现哲学家就餐问题实例代码

测试用例:

输入: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)

总结

到此这篇关于Python实现哲学家就餐问题的文章就介绍到这了,更多相关Python哲学家就餐内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
简单介绍使用Python解析并修改XML文档的方法
Oct 15 Python
python 正确保留多位小数的实例
Jul 16 Python
python实现linux下抓包并存库功能
Jul 18 Python
Python中使用__new__实现单例模式并解析
Jun 25 Python
给 TensorFlow 变量进行赋值的方式
Feb 10 Python
Python多个装饰器的调用顺序实例解析
May 22 Python
PythonPC客户端自动化实现原理(pywinauto)
May 28 Python
浅谈Python协程
Jun 17 Python
python如何实现读取并显示图片(不需要图形界面)
Jul 08 Python
Python如何实现线程间通信
Jul 30 Python
python接口自动化框架实战
Dec 23 Python
python 多线程爬取壁纸网站的示例
Feb 20 Python
使用Python实现NBA球员数据查询小程序功能
Nov 09 #Python
Python暴力破解Mysql数据的示例
Nov 09 #Python
python 实现一个图形界面的汇率计算器
Nov 09 #Python
python 读取串口数据的示例
Nov 09 #Python
Cpython解释器中的GIL全局解释器锁
Nov 09 #Python
OpenCV实现机器人对物体进行移动跟随的方法实例
Nov 09 #Python
基于python爬取梨视频实现过程解析
Nov 09 #Python
You might like
PHP逐行输出(ob_flush与flush的组合)
2012/02/04 PHP
探讨方法的重写(覆载)详解
2013/06/08 PHP
WHOOPS PHP调试库的使用
2017/09/29 PHP
laravel框架中间件简单使用方法示例
2020/01/25 PHP
如何用javascript控制上传文件的大小
2006/10/26 Javascript
JavaScript 读取元素的CSS信息的代码
2010/02/07 Javascript
iframe自适应宽度、高度 ie6 7 8,firefox 3.86下测试通过
2010/07/29 Javascript
说说JSON和JSONP 也许你会豁然开朗
2012/09/02 Javascript
如何阻止复制剪切和粘贴事件为了表单内容的安全
2013/05/23 Javascript
js unicode 编码解析关于数据转换为中文的两种方法
2014/04/21 Javascript
JavaScript中的style.cssText使用教程
2014/11/06 Javascript
js实现有时间限制消失的图片方法
2015/02/27 Javascript
Windows系统中安装nodejs图文教程
2015/02/28 NodeJs
网页前端登录js按Enter回车键实现登陆的两种方法
2016/05/10 Javascript
jQuery UI制作选项卡(tabs)
2016/12/13 Javascript
jquery与js实现全选功能的区别
2017/06/11 jQuery
Vue刷新修改页面中数据的方法
2018/09/16 Javascript
Vue项目中使用better-scroll实现一个轮播图自动播放功能
2018/12/03 Javascript
微信小程序与后台PHP交互的方法实例分析
2018/12/10 Javascript
JavaScript中AOP的实现与应用
2019/05/06 Javascript
JavaScript实现PC端横向轮播图
2020/02/07 Javascript
js实现无限层级树形数据结构(创新算法)
2020/02/27 Javascript
Python Web服务器Tornado使用小结
2014/05/06 Python
Python实现MySQL操作的方法小结【安装,连接,增删改查等】
2017/07/12 Python
Python3多进程 multiprocessing 模块实例详解
2018/06/11 Python
Python基于Opencv来快速实现人脸识别过程详解(完整版)
2019/07/11 Python
Python list与NumPy array 区分详解
2019/11/06 Python
Python之指数与E记法的区别详解
2019/11/21 Python
利用Python的sympy包求解一元三次方程示例
2019/11/22 Python
CSS3中的Transition过度与Animation动画属性使用要点
2016/05/20 HTML / CSS
英国信箱在线鲜花速递公司:Bloom & Wild
2019/03/10 全球购物
Michael Kors加拿大官网:购买设计师手袋、手表、鞋子、服装等
2019/03/16 全球购物
财务总监管理岗位职责
2014/03/08 职场文书
人力资源管理毕业求职信
2014/08/05 职场文书
八年级地理课件资料及考点知识分享
2019/08/30 职场文书
OpenCV图像变换之傅里叶变换的一些应用
2021/07/26 Python