GameMale
登陆 / 注册 搜索

USERCENTER

SEARCHSITE

搜索

查看: 1246|回复: 23
收起左侧

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

[复制链接] |关注本帖

寻觅眼镜蛇图腾香喷喷的烤鸡风雪之家牧羊人GM論壇榮譽勛章山猫图腾

     楼主| 白冥 发表于 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条回复 点击查看

        我也说一句

      回复

      使用道具 举报

      百相千面-晦永远的克叔業火死鬥实现梦想官复原职虚空之海的鲸Zootopia幸运女神的微笑『逆境中的幸运女神』御医神兔

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

        使用道具 举报

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

          回复

          使用道具 举报

          金猪猪储蓄罐㊖实现梦想業火死鬥魔法不朽·传奇不熄卡洛斯·奥利维拉白野威十年一梦官复原职男巫之歌永浴爱河

            回复

            使用道具 举报

            狩猎用小刀天使之赐破旧打火机满是血迹的徽章『崭新的红蓝游戏机』寻觅雄躯的昇格

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

              使用道具 举报

              神秘商店贵宾卡GHOST梅克军徽杰森‧斯坦森.上古卷轴V:天际炽天使之拥诡异的灵魂石冰海钓竿萨赫的蛋糕『迷翳之中』

                回复

                使用道具 举报

                内森·德雷克業火死鬥诺克提斯·路西斯·伽拉姆BIG BOSS克莱夫・罗兹菲尔德岛田半藏性感男神GM莱因哈特·威尔海姆

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

                  使用道具 举报

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

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

                    使用道具 举报

                    男巫之歌業火死鬥山村贞子月影狼

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

                      本帖子中包含更多资源

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

                      x
                      回复

                      使用道具 举报

                      金钱马车英雄联盟近地夜航赛博朋克2077瑞雪兆丰年,生灵万物新伪造的红石可爱黑猫

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

                        使用道具 举报

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

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

                          使用道具 举报

                          小丑与格雷与星光璀璨粉猪猪储蓄罐㊖劫掠核芯脉律辐石幸运女神的微笑诡异的灵魂石女神之泪卡勒罗斯辉石头罩马克赛博朋克2077

                            回复

                            使用道具 举报

                            石肤术小小安全帽魔眼护符骑兽之子召唤古代战士近地夜航元气菠菜人烈焰天使弓龙血指环『灰域来音』

                              回复

                              使用道具 举报

                              丹妮莉丝·坦格利安格拉迪欧拉斯雪王的心脏『星河碎片』『灰域来音』预知水晶球炽天使之拥『伊黎丝的赞词』纯真护剑『随时随地开启!』

                                回复

                                使用道具 举报

                                雄躯的昇格英雄联盟泰比里厄斯杰西·麦克雷萨菲罗斯『星象监测』邪恶圣杯GM論壇榮譽勛章

                                  回复

                                  使用道具 举报

                                  十字军护盾诡异的灵魂石我的冶金打火机不曾寄出的信件成年独角兽苏醒的格罗姆落雪勇者与龙的传说-封面初入动物城

                                    回复

                                    使用道具 举报

                                    安德鲁·库珀索尔·奥丁森.安德森‧戴维斯.走出失恋阴影的罗罗詹米·多南.

                                      回复

                                      使用道具 举报

                                      脉律辐石劫掠核芯御医神兔夏日柯基幽灵竹筒黄金树的恩惠探险三杰士图腾饼干生活拍立得璀璨金币

                                        回复

                                        使用道具 举报

                                        魔法石碑吃饱的小阿尔驯化黑龙幼崽新月护符森林羊男夜灯牧羊人近地夜航

                                          回复

                                          使用道具 举报

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

                                          本版积分规则

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

                                          GMT+8, 2024-11-21 16:52 , Processed in 0.191437 second(s), 143 queries , Redis On.

                                          Copyright © 2013-2024 GameMale

                                          All Rights Reserved.

                                          快速回复 返回列表