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数据库操作常用功能使用详解(创建表/插入数据/获取数据)
Dec 06 Python
轻松实现python搭建微信公众平台
Feb 16 Python
浅谈Python2.6和Python3.0中八进制数字表示的区别
Apr 28 Python
python生成不重复随机数和对list乱序的解决方法
Apr 09 Python
python3解析库lxml的安装与基本使用
Jun 27 Python
python3 下载网络图片代码实例
Aug 27 Python
PyTorch笔记之scatter()函数的使用
Feb 12 Python
在Anaconda3下使用清华镜像源安装TensorFlow(CPU版)
Apr 19 Python
Python工程师必考的6个经典面试题
Jun 28 Python
pycharm不以pytest方式运行,想要切换回普通模式运行的操作
Sep 01 Python
Python性能测试工具Locust安装及使用
Dec 01 Python
如何在Python中妥善使用进度条详解
Apr 05 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+SQL 注入攻击的技术实现以及预防办法
2010/12/29 PHP
PHP5.5在windows安装使用memcached服务端的方法
2014/04/16 PHP
如何在Laravel之外使用illuminate组件详解
2020/09/20 PHP
JS location几个方法小姐
2008/07/09 Javascript
fckeditor 获取文本框值的实现代码
2009/02/09 Javascript
javascript 异常处理使用总结
2009/06/21 Javascript
Javascript 面向对象编程(一) 封装
2011/08/28 Javascript
JavaScript转换农历类实现及调用方法
2013/01/27 Javascript
jquery限定文本框只能输入数字即整数和小数
2013/11/29 Javascript
JS实现屏蔽shift,Ctrl,alt等功能键的方法
2015/06/01 Javascript
jquery+html5烂漫爱心表白动画代码分享
2015/08/24 Javascript
JS实现光滑展开合拢的菜单效果代码
2015/09/16 Javascript
有关Promises异步问题详解
2015/11/13 Javascript
jquery 点击元素后,滚动条滚动至该元素位置的方法
2016/08/05 Javascript
浅谈JavaScript的innerWidth与innerHeight
2017/10/12 Javascript
使用async await 封装 axios的方法
2018/07/09 Javascript
vue watch深度监听对象实现数据联动效果
2018/08/16 Javascript
JS双向链表实现与使用方法示例(增加一个previous属性实现)
2019/01/31 Javascript
javascript实现切割轮播效果
2019/11/28 Javascript
js里面的变量范围分享
2020/07/18 Javascript
js实现贪吃蛇小游戏(加墙)
2020/07/31 Javascript
python输出指定月份日历的方法
2015/04/23 Python
python使用正则筛选信用卡
2019/01/27 Python
python Tkinter版学生管理系统
2019/02/20 Python
Python实现计算文件MD5和SHA1的方法示例
2019/06/11 Python
解决Python正则表达式匹配反斜杠''\''问题
2019/07/17 Python
Python批量处理csv并保存过程解析
2020/05/16 Python
利用Python实现最小二乘法与梯度下降算法
2021/02/21 Python
北欧最好的童装网上商店:Babyshop
2019/09/15 全球购物
《北京的春节》教学反思
2014/04/07 职场文书
综合实践活动总结
2014/05/05 职场文书
聚众斗殴罪辩护词
2015/05/21 职场文书
《詹天佑》教学反思
2016/02/20 职场文书
股东协议书范本2016
2016/03/21 职场文书
JPA如何使用entityManager执行SQL并指定返回类型
2021/06/15 Java/Android
分布式架构Redis中有哪些数据结构及底层实现原理
2022/03/13 Redis