zoukankan      html  css  js  c++  java
  • 哲学家就餐问题

    问题描述:

    五个哲学家(A~E)围着一张圆桌就餐,他们每个人面前都有一盘通心粉。由于通心粉很滑,所以需要两只筷子才能夹住,但每两个盘子之间只放着一只筷子,如下图。
    哲学家只有两个动作:要么就餐,要么思考。而且他们之间从不交谈。
    当一个哲学家饿了的时候,就拿起盘子左右两边的筷子开始就餐(不能同时拿起两只筷子)。就餐完以后,就把筷子放回盘子左右,继续思考。
    这里写图片描述

    由于他们之间互不交谈,所以很容易出现“死锁”:假如每个人都拿着左边的筷子,则所有人都在等右边的筷子,谁都吃不了。
    我们可以规定,拿着一只筷子等待另一只筷子的时间超过五分钟就放下手中的筷子,并且再等待五分钟之后进行下一次尝试。
    这个策略消除了死锁,不过还是有可能发生“活锁”:假如这五个人同时拿起左边的筷子,大家都在等另一只筷子,五分钟之后大家同时放下筷子。再过五分钟之后又同时拿起左边的筷子……

    在计算机领域中,哲学家就餐问题可以抽象成资源抢占问题,筷子就是“资源”。一种常用的计算机技术就是给资源“加锁”,一个资源同时只能供一个程序或者一段代码访问。当一个程序要使用的资源被另外一个程序锁定的时候,只能等待资源被解锁。这就容易出现死锁情况,当有两个程序需要访问两个相同的资源时,如果每个程序都锁了一个资源,那么两者都在等待对方解锁另一个资源的解锁,最后谁都无法执行。

    以下介绍三种解决方案。


    服务生

    就就餐问题,我们可以引入一个服务生,哲学家要经过服务生同意才能拿筷子,因为服务生知道哪只筷子在使用,他可以阻止死锁的发生。
    这很好理解,只有当盘子左右的筷子都空闲的时候,服务生才会同意哲学家就餐,这样就不存在有人拿着一只筷子在等待另一只筷子的情况,也就杜绝了死锁的发生。


    资源分级

    另外一种方法就是给资源分级,例如上图中的五只筷子,给它们分级为1~5五个等级。
    约定:每位哲学家在就餐拿筷子的时候,只能先拿级别比较低的筷子,然后才能拿级别比较高的。用餐完以后,先放下级别比较高的筷子,再放下编号比较低的。

    这样也不会出现死锁的情况。
    假如大家同时拿起一只筷子,那么级别最高的5号筷子一定还留在桌子上。此时哲学家A或者E就能拿起它凑成两只筷子开始进餐。进餐完以后放下筷子,其他哲学家又能进餐了……


    Chandy/Misra

    这是由K. Mani Chandy和J. Misra提出的又一种解法:

    1. 刚开始的时候,把每只筷子都分给编号比较小的哲学家,即有:A~1,B~2,C~3,D~4,E~5。并把筷子都定义为“脏的”。
    2. 当某位哲学家要使用筷子的时候,他缺哪只筷子,就向拥有那只筷子的哲学家发送一个请求。
    3. 当拥有筷子的哲学家收到请求时,如果筷子是脏的,就把筷子擦干净并交出去;否则就继续留着。
    4. 当哲学家拥有两只干净的筷子时就可以就餐了,吃完以后筷子就变成脏的了。如果有哲学家之前请求过其中一只筷子,则把筷子擦干净并交出去。

    示例:

    1. 起初,先把 5 只筷子分别分给 A~E 五位哲学家,并定义为脏的。
    2. 假设B想要吃东西了,他把手里的2号筷子擦干净,可是还缺1号筷子呀,于是就向拥有1号筷子的A发送一个请求。
    3. A收到请求,因为此时1号筷子是脏的,所以A得把1号筷子擦干净,并交给B。
    4. B有两只筷子了,准备开吃了。可就在此时,C也想吃东西了,向B发送过来一个请求,想要2号筷子。
    5. B手里的2号筷子是干净的呀,于是B先吃自己的,吃完以后2号筷子变成脏的了,B再把筷子擦干净并交给C。
      …………
      …………
  • 相关阅读:
    C#秘密武器之表达式树
    C#秘密武器之特性
    [转]拷贝构造函数详解
    [转]STL 容器一些底层机制
    C++ Qt多线程 TcpSocket服务器实例
    QByteArray储存二进制数据(包括结构体,自定义QT对象)
    [转]浅谈 C++ 中的 new/delete 和 new[]/delete[]
    [转]QList内存释放
    Subscribe的第四个参数用法
    ROS多线程订阅消息
  • 原文地址:https://www.cnblogs.com/Bone-ACE/p/4558872.html
Copyright © 2011-2022 走看看