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 正则式使用心得
May 07 Python
python中二维阵列的变换实例
Oct 09 Python
web.py 十分钟创建简易博客实现代码
Apr 22 Python
Python使用smtplib模块发送电子邮件的流程详解
Jun 27 Python
python简单实例训练(21~30)
Nov 15 Python
Python 比较文本相似性的方法(difflib,Levenshtein)
Oct 15 Python
python生成n个元素的全组合方法
Nov 13 Python
Python 依赖库太多了该如何管理
Nov 08 Python
python多进程 主进程和子进程间共享和不共享全局变量实例
Apr 25 Python
Python直接赋值及深浅拷贝原理详解
Sep 05 Python
Python调用飞书发送消息的示例
Nov 10 Python
Python+Tkinter打造签名设计工具
Apr 01 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下MYSQL limit的优化
2008/01/10 PHP
php中的curl使用入门教程和常见用法实例
2014/04/10 PHP
JS中彻底删除JSON对象组成的数组中的元素
2020/09/22 PHP
关于JavaScript中原型继承中的一点思考
2012/07/25 Javascript
获取div编辑框,textarea,input text的光标位置 兼容IE,FF和Chrome的方法介绍
2012/11/08 Javascript
JavaScript日期时间格式化函数分享
2014/05/05 Javascript
js和jquery中循环的退出和继续学习记录
2014/09/06 Javascript
js实现从数组里随机获取元素
2015/01/12 Javascript
JavaScript实现更改网页背景与字体颜色的方法
2015/02/02 Javascript
AngularJS入门心得之directive和controller通信过程
2016/01/25 Javascript
JavaScript+html5 canvas绘制的小人效果
2016/01/27 Javascript
DWR中各种java方法的调用
2016/05/04 Javascript
js+html5实现canvas绘制椭圆形图案的方法
2016/05/21 Javascript
用file标签实现多图文件上传预览
2017/02/14 Javascript
JS简单封装的图片无缝滚动效果示例【测试可用】
2017/03/22 Javascript
jQuery实现火车票买票城市选择切换功能
2017/09/15 jQuery
nodejs使用http模块发送get与post请求的方法示例
2018/01/08 NodeJs
基于vue开发的在线付费课程应用过程
2018/01/25 Javascript
在Angular中使用JWT认证方法示例
2018/09/10 Javascript
微信小程序实现的动态设置导航栏标题功能示例
2019/01/31 Javascript
微信小程序 如何保持登录状态
2019/08/16 Javascript
TypeScript类型声明书写详解
2019/08/28 Javascript
微信小程序实现注册登录功能(表单校验、错误提示)
2019/12/10 Javascript
Python图形绘制操作之正弦曲线实现方法分析
2017/12/25 Python
python实现TCP文件传输
2020/03/20 Python
python小白切忌乱用表达式
2020/05/29 Python
CSS3点击按钮实现背景渐变动画效果
2016/10/19 HTML / CSS
美国迪克体育用品商店:DICK’S Sporting Goods
2018/07/24 全球购物
网站开发实习生的自我评价
2013/12/11 职场文书
精通CAD能手自荐书
2014/01/31 职场文书
公司委托书格式范文
2014/10/09 职场文书
拾金不昧通报表扬范文
2015/05/05 职场文书
2015年科研工作总结范文
2015/05/13 职场文书
采购部2015年度工作总结
2015/07/24 职场文书
公司员工宿舍管理制度
2015/08/03 职场文书
Redis高并发防止秒杀超卖实战源码解决方案
2021/11/01 Redis