GameMale
登陆 / 注册 搜索

USERCENTER

SEARCHSITE

搜索

查看: 861|回复: 19
收起左侧

[技术交流] 【并发编程】哲学家饥饿问题的代码实现

[复制链接] |关注本帖

牧羊人

     楼主| 白冥 发表于 2024-5-18 01:46:17 | 显示全部楼层 |阅读模式 |取消关注该作者的回复
    1. import threading
    2. import time
    3. class Consumption:
    4.     def __init__(self, counts):
    5.         self.counts=counts
    6.         self.forks=[Fork() for _ in range(self.counts)]
    7.         self.philosophers=[Philosopher(i) for i in range(self.counts)]
    8.     def consumption(self, position):
    9.         philosopher=self.philosophers[position]
    10.         left_fork, right_fork = self.forks[position], self.forks[(position+1) % self.counts]
    11.         first_fork = left_fork if position%2 == 0 else right_fork
    12.         second_fork=right_fork if position%2==0 else left_fork
    13.         while  not philosopher.leave:
    14.             philosopher.with_forks(first_fork, second_fork)
    15. class Fork:
    16.     def __init__(self):
    17.         self.lock=threading.Lock()
    18.     def wait(self):
    19.         try:
    20.             self.lock.acquire(timeout=3)
    21.             return True
    22.         except threading.Timeout:
    23.             return False
    24.     def signal(self):
    25.         self.lock.release()
    26. class Philosopher:
    27.     def __init__(self,position):
    28.         self.satiety=50
    29.         self.leave=False
    30.         self.position=position
    31.         self.forks=[]
    32.     def with_forks(self, *forks):
    33.         for fork in forks:
    34.             if not fork.wait():
    35.                 self.reduce()
    36.                 return
    37.             else:
    38.                 self.forks.append(fork)
    39.         self.eat()
    40.     def put_forks(self):
    41.         counts=len(self.forks)
    42.         for i in range(counts):
    43.             self.forks[i].signal()
    44.             self.forks.pop(i)
    45.     def eat(self,):
    46.         time.sleep(10)
    47.         self.rise()
    48.     def anger(self):
    49.         self.put_forks()
    50.         self.leave=True
    51.         print(f"Dr.{self.position} is so hungry that he can't bear it and decide to leave.")
    52.     def be_full(self,philosopher):
    53.         self.put_forks()
    54.         self.leave=True
    55.         print(f"Dr.{self.position} feel satisfied and leave the table.")
    56.     def rise(self):
    57.         if self.satiety>=0 and self.satiety<100:
    58.             self.satiety+=10
    59.         else:
    60.             self.be_full()
    61.     def reduce(self):
    62.         if self.satiety>=0 and self.satiety<100:
    63.             self.satiety-=10
    64.         else:
    65.             self.anger()
    66. if __name__=="__main__":
    67.     counts=5
    68.     consumption=Consumption(counts)
    69.     for i in range(counts):
    70.           threading.Thread(target=consumption.consumption,args=(i,)).start()  
    复制代码
           哲学家饥饿问题是计算机科学家迪杰斯特拉(Dijkstra)提出的经典并发问题。
            有5个哲学家(线程)坐在圆桌上,每个哲学家之间放着一把叉子。一个哲学家要吃饭,他需要左右两边的叉子。如果相邻的两个哲学家同时试图拿起中间的叉子,就可能产生死锁。

    • Consumption类初始化时,根据传入的哲学家数量(counts)创建相应数量的叉子和哲学家对象。
    • consumption方法用于模拟某位哲学家的就餐过程。根据哲学家的位置,确定他需要获取的叉子的顺序(先左后右或先右后左,以避免死锁),并尝试拿起叉子吃饭。
    • Fork类表示叉子,包含一个线程锁来控制对叉子的访问。wait方法尝试获取锁,如果获取成功返回True,否则在设定的超时时间后返回False。signal方法用于释放锁。
    • Philosopher类代表哲学家,包含哲学家的状态(如满意度、是否离开等)和与叉子交互的方法(如拿起叉子、放下叉子等)。
    • 在Philosopher类中,with_forks方法尝试让哲学家拿起左右两边的叉子,如果拿起成功则开始吃饭,否则根据哲学家的满意度决定是否离开。
    • eat方法模拟吃饭过程,吃完后增加哲学家的满意度。
    • anger和be_full方法分别模拟哲学家因饥饿而愤怒离开和吃饱后满意离开的情况。
    • rise和reduce方法分别用于增加和减少哲学家的满意度。


      收起(1)
    • 白冥 白冥 :这段代码通过一些策略来避免死锁:

      哲学家编号与叉子获取顺序:根据哲学家的编号(偶数或奇数),他们首先尝试拿起左边的叉子或右边的叉子。这有助于防止相邻的哲学家同时拿起同一把叉子,从而降低死锁的风险。

      锁的超时机制:在尝试获取叉子(即锁)时,设置了一个3秒的超时时间。如果超时,则放弃获取叉子,这也有助于防止死锁。

      哲学家的状态:每个哲学家有一个“饥饿度”(satiety),当他们成功吃到时,饥饿度会降低;如果因为超时而未能获取到叉子,饥饿度会增加。当饥饿度达到100时,哲学家会感到满足并离开桌子;当饥饿度降到0以下时,哲学家会因为太饿而生气地离开桌子。
      2024-05-18 01:48 回复
    • 我也说一句

    回复

    使用道具 举报

    恶魔城沼泽黏附者驯化黑龙幼崽

      好像可以用于解决同时请求量过大的问题
        不过我也不是码农,就是这样想想
        收起(8)
      • 白冥 白冥 :死锁和饥饿不是解决高并发的问题的
        2024-05-18 02:21 回复
      • 白冥 白冥 :在计算机领域中,饥饿不是人类的饥饿,而是表示线程获取不到资源的状况叫“饥饿”;
        死锁则是因为程序逻辑问题造成的互相等待资源而造成的,会引发系统性饥饿。
        2024-05-18 02:24 回复
      • 白冥 白冥 :举个例子,亚瑟王请十二圆桌骑士吃饭,结果亚瑟王的妻子记错了人数,只拿了12个叉子,这十二个人死倔,拿到叉子除非吃完否则不愿意放手,结果他们同时伸出左手,导致每个人左手都拿到叉子,右手都在等叉子,结果是大家都吃不到饭。
        这就是死锁。
        2024-05-18 02:28 回复
      • 夏漏光微 夏漏光微 :回复 白冥 :哇,感谢回复这么多。是这样理解吗?死锁面对的问题是12个人都去拿叉子,死锁排了个队伍让大家能依次吃饭,虽然高并发看上去也可以通过死锁排队解决,但高并发面对的是12000个人,死锁的排队对于高并发来说并不适合。
        2024-05-18 03:09 回复
      • 白冥 白冥 :很抱歉我必须告诉你,死锁不是解决方法,也跟人数毫无关系。死锁是一种问题、错误、计算机必须避免的玩意,它是多个同步请求互相等待共享资源造成的严重问题。高并发是一种模式,指的是同一时间服务器处理io复杂型并发的push升级版。
        2024-05-18 07:10 回复
      • 白冥 白冥 :你的问题在于先入为主的把死锁和高并发想在一块,但二者毫无关系,在无论是不是高并发,都会发生死锁。
        2024-05-18 07:12 回复
      • 还有2条回复 点击查看

        我也说一句

      回复

      使用道具 举报

      月棱镜内森·德雷克官复原职实现梦想虚空之海的鲸永远的克叔『召唤好运的角笛』敖蜃星风物长宜永浴爱河

        实际应用中解决死锁的策略好像还挺多的
          收起(1)
        回复

        使用道具 举报

        诺克提斯·路西斯·伽拉姆業火死鬥钢铁侠永远的克叔极·龙の意死灵之书卡利亚权杖虚空之海的鲸史莱姆牧场男巫之歌

          回复

          使用道具 举报

          虚空之海的鲸实现梦想官复原职永浴爱河白野威業火死鬥十年一梦男巫之歌

            回复

            使用道具 举报

            寻觅满是血迹的徽章破旧打火机天使之赐为承父志『崭新的红蓝游戏机』森林羊男GM論壇榮譽勛章琉璃玉坠迷拟Q

              死锁以外 还有未达成指令后同时再激活还是同时抢一个叉子的活锁问题之类的
              总感觉是什么奥数还是啥地方看到过的问题
              回复

              使用道具 举报

              思绪骤聚『灰域来音』神秘商店贵宾卡初遇朱迪野兽之子『住在GM村』萨菲罗斯『伊黎丝的赞词』瑞雪兆丰年,生灵万物新炼金之心

                回复

                使用道具 举报

                雷霆晶球丹雀衔五穗,人间始丰登收到情书变身器石肤术没有梦想的咸鱼克莱夫・罗兹菲尔德骑兽之子岛田半藏性感男神GM

                  koh 发表于 2024-5-18 09:32:27 | 显示全部楼层 |取消关注该作者的回复
                  懂了!这个程序就是为了最大程度上让每一个人都只拿一件东西,且不重复
                    收起(4)
                  回复

                  使用道具 举报

                  亚索月影狼晓月终焉旅行骰子!卡利亚权杖

                    虽然有点跑题,但哲学家这种好像都是死后才会出名/更加出名,所以…… 要不还是饿死几个吧
                    回复

                    使用道具 举报

                    启示录旧日支配者—克苏鲁山村贞子月影狼

                      用代码跑个现实问题,emmm想到了一张图:

                      本帖子中包含更多资源

                      您需要 登录 才可以下载或查看,没有账号?立即注册

                      x
                      回复

                      使用道具 举报

                      知识大典赛博朋克2077崭新的白袜瑞雪兆丰年,生灵万物新蒂法·洛克哈特森林羊男可爱黑猫神秘挑战书男用贞操带破旧打火机

                        看起来有点像嵌入式编程里的优先级问题,不过不知道解决思路是不是差不多的
                        回复

                        使用道具 举报

                        我的天使GM吸血伯爵吃饱金币的Doge阿拉喵?神灯和你一起飞行的皮卡丘小小舞台永浴爱河

                          吼(´×ω×`)看了8楼楼主的解释大概明白了些欸~也可以编辑进帖子里方便菜鸡们(咱)理解的哇~
                          回复

                          使用道具 举报

                          变身器没有梦想的咸鱼『住在GM村』『灰域来音』『伊黎丝的赞词』夜灯风雪之家萨赫的蛋糕禽兽扒手夏之歌

                            回复

                            使用道具 举报

                            元气菠菜人狱炎魔犬石鬼面『伊黎丝的赞词』SCP-s-1889-第七页钢铁勇士弯刀石肤术生活拍立得阿怪阿帕茶

                              回复

                              使用道具 举报

                              『住在GM村』预知水晶球炽天使之拥『伊黎丝的赞词』纯真护剑『随时随地开启!』『随时随地开启!』神奇四叶草深渊遗物夏日柯基

                                回复

                                使用道具 举报

                                英雄联盟泰比里厄斯杰西·麦克雷『星象监测』GM論壇進階勛章史莱姆蛋马戏团狂欢象破损的旧书森林羊男

                                  回复

                                  使用道具 举报

                                  漂洋小船『正在入住GM村』黑龙幼崽龙腾世纪:审判最终幻想XIV

                                    回复

                                    使用道具 举报

                                    安德鲁·库珀詹米·多南安德森‧戴维斯

                                      回复

                                      使用道具 举报

                                      夏日柯基幽灵竹筒黄金树的恩惠

                                        回复

                                        使用道具 举报

                                        炼金之心『正在入住GM村』最终幻想XIV赛博朋克2077收到情书喋血日记本夜灯水泡术荒野大镖客:救赎 II【新手友好】昆進

                                          回复

                                          使用道具 举报

                                          您需要登录后才可以回帖 登录 | 立即注册

                                          本版积分规则

                                          文字版|手机版|小黑屋|GameMale

                                          GMT+8, 2024-6-16 01:57 , Processed in 0.127302 second(s), 143 queries , Redis On.

                                          Copyright © 2013-2024 GameMale

                                          All Rights Reserved.

                                          快速回复 返回列表