问题描述

哲学家就餐问题(Dining philosophers problem)是在计算机科学中的一个经典问题,用来演示在并发计算中多线程同步(Synchronization)时产生的问题。 哲学家就餐问题可以这样表述:五位哲学家围绕一个圆桌就坐,桌上摆着五 支 筷子。哲学家的状态可能是“思考”或者“饥饿”。如果饥饿,哲学家将拿起他两边的筷子并进餐一段时间。进餐结束,哲学家就会放回筷子。哲学家从来不交谈,这就很危险,会产生每个哲学家都拿着左边的筷子,一直在等右边的筷子的情况。

可以用如下的代码表示这个问题:

import threading

import time

import random

import os

import sys

import signal

class Watcher():

def __init__(self):

self.child = os.fork()

if self.child == 0:

return

else:

self.watch()

def watch(self):

try:

os.wait()

except KeyboardInterrupt:

self.kill()

sys.exit()

def kill(self):

try:

os.kill(self.child, signal.SIGKILL)

except OSError:

pass

class Philosopher(threading.Thread):

def __init__(self, left, right):

threading.Thread.__init__(self)

self.left = left

self.right = right

def run(self):

while True:

# now thinking random time

time.sleep(random.random())

# now picking up chopsticks

with self.left:

with self.right:

# now eating

print '%s is eating %s' % (threading.currentThread().getName(), time.ctime())

time.sleep(random.random())

if __name__ == '__main__':

num = 5

chopsticks = [threading.Lock() for _ in range(num)]

philosophers = [Philosopher(chopsticks[(_ - 1) % num],

chopsticks[_ % num])for _ in range(num)]

Watcher()

for p in philosophers:

p.start()

上面这段代码产生死锁的概率比较小,运行了两个小时还没出现(可见死锁问题调试时难以被发现)。为了让死锁更容易出现我们稍加修改,假设哲学家们拿起左面的筷子后突然忘记了自己要吃饭,沉思一会后,再拿起右面的筷子去吃饭。

with self.left:

time.sleep(random.random())

with self.right:

Output

Thread-4 is eating Tue Sep 13 13:15:20 2016

Thread-3 is eating Tue Sep 13 13:15:21 2016

...

Thread-3 is eating Tue Sep 13 13:16:15 2016

Thread-2 is eating Tue Sep 13 13:16:15 2016

# block here

当一个线程想要使用多把锁时,就需要考虑死锁。 有一种方案是在获取第二把锁的时候设置超时时间,这种方案虽然避免了无尽的死锁,但这并不是一个足够好的方案。首先,这个方案并不能避免死锁——它只是提供了一种从死锁中恢复的手段。其次,这个方案会受到活锁现象的影响——如果所有死锁线程同时超时,它们极有可能再次陷入死锁。虽然死锁没有永远持续下去,但对资源的争夺状况却没有得到任何改善。

下面给出两种避免死锁的方法

固定顺序获取

有一个简单的方法可以避开死锁——总是按照一个全局的固定的顺序获取多把锁。

class Philosopher(threading.Thread):

def __init__(self, left, right):

threading.Thread.__init__(self)

if id(left) < id(right):

self.first = left

self.second = right

else:

self.first = right

self.second = left

def run(self):

while True:

# now thinking random time

time.sleep(random.random())

# now picking up chopsticks

with self.first:

time.sleep(random.random())

with self.second:

# now eating

print '%s is eating %s' % (threading.currentThread().getName(), time.ctime())

time.sleep(random.random())

条件变量

class Philosopher(threading.Thread):

def __init__(self, con):

threading.Thread.__init__(self)

self.is_eating = False

self.con = con

def set_around(self, left, right):

self.left = left

self.right = right

def thinking(self):

with self.con:

self.is_eating = False

self.left.con.notify()

self.right.con.notify()

time.sleep(random.random())

def eating(self):

with self.con:

while self.left.is_eating or self.right.is_eating:

self.con.wait()

self.is_eating = True

print '%s is eating %s' % (threading.currentThread().getName(), time.ctime())

time.sleep(random.random())

def run(self):

while True:

self.thinking()

self.eating()

if __name__ == '__main__':

num = 5

con = threading.Condition()

philosophers = [Philosopher(con) for _ in range(num)]

for i in range(num):

philosophers[i].set_around(

philosophers[(i - 1) % num], philosophers[i % num])

Watcher()

for p in philosophers:

p.start()

与之前不同,我们将竞争从对筷子的竞争转换成了对状态的判断:仅当哲学家的左右都没有进餐时,他才可以进餐。

哲学家就餐问题python_哲学家就餐问题与死锁相关推荐

  1. 哲学家就餐问题python_哲学家就餐-同步问题解析-python

    五个哲学家吃五盘通心粉,由于通心粉很滑,所以必须要拿起左右两边的叉子才能吃到. 叉子的摆放如图所示. 那么问题来了:能为每一个哲学家写一段描述其行为的程序,保证不会出现死锁. 解法1:让他等待能够使用 ...

  2. 哲学家就餐问题--信号量和互斥量预防死锁

    哲学家就餐问题可以采取预防死锁的方案,就是使用互斥量和信号量锁定资源. 互斥量: 对资源进行锁定的意思就是说,当一个哲学家使用叉子的时候,他首先要先把叉子锁定,然后,拿起来.这个时候如果别的哲学家也来 ...

  3. php 哲学家进餐,IPC问题-哲学家就餐(示例代码)

    如上图,有五位哲学家,盘中的食物只有左右两个叉子都拿起才能吃.哲学家在桌上只有思考(等待)和吃面(执行).看起来最多是只有2个人能同时吃. 版本一:这个思路的最糟糕的就是都拿起左边叉子,那样都没法吃了 ...

  4. 哲学家就餐 java_java模拟哲学家就餐问题

    废话不多说 直接上代码 1.筷子类 他有两个属性, 一个是标示这根筷子在哪个哲学家手边,另一个属性标示这个筷子的状态,并且这个状态是随时从内存当中取出的 package com.bjs.dinning ...

  5. 哲学家就餐问题c语言_哲学家就餐问题的一种Python解决方案

    哲学家就餐问题一直是多线程同步问题的经典案例,本文中展示了多线程竞争共享资源带来的死锁问题,并介绍了一种简单的解决方案. 哲学家就餐问题 哲学家最擅长的就是思考和吃饭 ,当他们感觉累的时候,就会拿起一 ...

  6. 哲学家就餐问题php代码,Python实现哲学家就餐问题实例代码

    哲学家就餐问题: 哲学家就餐问题是典型的同步问题,该问题描述的是五个哲学家共用一张圆桌,分别坐在五张椅子上,在圆桌上有五个盘子和五个叉子(如下图),他们的生活方式是交替的进行思考和进餐,思考时不能用餐 ...

  7. 哲学家就餐问题python_Python实现哲学家就餐问题实例代码

    哲学家就餐问题: 哲学家就餐问题是典型的同步问题,该问题描述的是五个哲学家共用一张圆桌,分别坐在五张椅子上,在圆桌上有五个盘子和五个叉子(如下图),他们的生活方式是交替的进行思考和进餐,思考时不能用餐 ...

  8. Java多线程学习四十二:有哪些解决死锁问题的策略和哲学家就餐问题

    线上发生死锁应该怎么办 如果线上环境发生了死锁,那么其实不良后果就已经造成了,修复死锁的最好时机在于"防患于未然",而不是事后补救.就好比发生火灾时,一旦着了大火,想要不造成损失去 ...

  9. Thinking in Java---从哲学家就餐问题看死锁现象

    我们知道一个对象可以有synchronized方法或其他形式的加锁机制来防止别的线程在互斥还没释放的时候就访问这个对象.而且我们知道线程是会变成阻塞状态的(挂起),所以有时候就会发生死锁的情况:某个任 ...

最新文章

  1. 【码书】一本经典且内容全面算法书籍,学算法必备
  2. 非计算机专业自学1年拿到算法offer的总结(附学习路线)
  3. 无需服务器的个人博客 (2018.5.22更新)
  4. css中怎么令dt 和 dd对齐
  5. shell中的>/dev/null 2>1(转载)
  6. 江西财经大学第二届程序设计竞赛同步赛 H大时钟 (扩展欧几里得)
  7. python程序题斐波那契数列_Python编程题9--斐波那契数列
  8. java web应用开发期末考试_Java开发工程师(Web方向) - 04.Spring框架 - 期末测试
  9. 集成ueditor后显示html问题处理
  10. C#读取数据库返回泛型集合(DataSetToList)
  11. 有软件测试台式电脑电源供电不足吗,台式机电源供电不足的原因
  12. C语言中的万能头文件
  13. 空气螺旋桨,让水下动物不再受伤害
  14. 开发计算机软件的基本流程
  15. 山东省第五届ACM大赛--Problem E: Full Binary Tree
  16. 【linux】系统压力模拟工具stress
  17. 邮件中的FYI和PFA代表什么意思
  18. c++标准扩展TR1
  19. android多个module打包aar,android 多module打包aar
  20. win10自带邮箱客户端登录163邮箱:无法访问该账户,需要更新密码或授权码

热门文章

  1. 01.Signal and Image Noise Models 信号与图像噪声模型
  2. 直流有刷电机H桥正反转调速原理及Matlab/Simulink仿真
  3. KEIL4/5的背景色修改
  4. Maven之pom.xml与setting.xml配置文件详解
  5. 看图工具 -- 蓝湖 Axure 墨刀
  6. 使用跳板机实现外网访问局域网内虚拟机的大数据及K8S集群【借助向日葵】
  7. Android UI学习组件概述
  8. c mysql 返回字符串长度_C字符串截取、C数据库操作
  9. nginx常见502错误的解决方法
  10. LMS自适应滤波器算法及其改进