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

    如上图,有五位哲学家,盘中的食物只有左右两个叉子都拿起才能吃。哲学家在桌上只有思考(等待)和吃面(执行)。看起来最多是只有2个人能同时吃。

    版本一:这个思路的最糟糕的就是都拿起左边叉子,那样都没法吃了,直接死锁。

    版本二:改进版本一,如果拿起左边叉子,先看右边是否能用,不可用的话放下左边叉子等待一段时间再运行。这个思路的问题就是,会产生某个时刻每个人都拿起左叉子,又放下,又拿起,虽然没有死锁,但是没有人在吃面,消耗了性能但是任务没有进展,造成饥饿。

    版本三:改进版本二,每次等待右边是否能用的每个哲学家(线程)时间不一样,这个方法看起来ok,但是考虑到极度糟糕情况下,它仍不能稳定,对于极度要求稳定的场合显然也是不合适的。

    版本四:我们可以对think后加一个互斥量,就是在拿起左叉子前,就加上一个互斥量,别人就没法拿叉子了,放下互斥量在去掉,但问题是性能差,一次只能有一位人吃面,一开始我们就分析过其实可以两个人同时吃的。

    这是新的解法:其实就是在版本四的基础上对每个要拿起叉子的哲学家进行了left 和 right的饥饿状态判断,只有当邻居都不在饮食的基础上才能饮食。这样既不会死锁也不会饥饿,且性能满足了。

    下面为Wiki的解释和方法:

    服务生解法

    一个简单的解法是引入一个餐厅服务生,哲学家必须经过他的允许才能拿起餐叉。因为服务生知道哪只餐叉正在使用,所以他能够作出判断避免死锁。

    为了演示这种解法,假设哲学家依次标号为A至E。如果A和C在吃东西,则有四只餐叉在使用中。B坐在A和C之间,所以两只餐叉都无法使用,而D和E之间有一只空余的餐叉。假设这时D想要吃东西。如果他拿起了第五只餐叉,就有可能发生死锁。相反,如果他征求服务生同意,服务生会让他等待。这样,我们就能保证下次当两把餐叉空余出来时,一定有一位哲学家可以成功的得到一对餐叉,从而避免了死锁。

    资源分级解法

    另一个简单的解法是为资源(这里是餐叉)分配一个偏序或者分级的关系,并约定所有资源都按照这种顺序获取,按相反顺序释放,而且保证不会有两个无关资源同时被同一项工作所需要。在哲学家就餐问题中,资源(餐叉)按照某种规则编号为1至5,每一个工作单元(哲学家)总是先拿起左右两边编号较低的餐叉,再拿编号较高的。用完餐叉后,他总是先放下编号较高的餐叉,再放下编号较低的。在这种情况下,当四位哲学家同时拿起他们手边编号较低的餐叉时,只有编号最高的餐叉留在桌上,从而第五位哲学家就不能使用任何一只餐叉了。而且,只有一位哲学家能使用最高编号的餐叉,所以他能使用两只餐叉用餐。当他吃完后,他会先放下编号最高的餐叉,再放下编号较低的餐叉,从而让另一位哲学家拿起后边的这只开始吃东西。

    尽管资源分级能避免死锁,但这种策略并不总是实用的,特别是当所需资源的列表并不是事先知道的时候。例如,假设一个工作单元拿着资源3和5,并决定需要资源2,则必须先要释放5,之后释放3,才能得到2,之后必须重新按顺序获取3和5。对需要访问大量数据库记录的计算机程序来说,如果需要先释放高编号的记录才能访问新的记录,那么运行效率就不会高,因此这种方法在这里并不实用。

    Chandy/Misra解法

    1984年,K. Mani Chandy和J. Misra提出了哲学家就餐问题的另一个解法,允许任意的用户(编号{displaystyle P_{1},cdots ,P_{n}}{displaystyle P_{1},cdots ,P_{n}})争用任意数量的资源。与资源分级解法不同的是,这里编号可以是任意的。

    • 把餐叉凑成对,让要吃的人先吃,没餐叉的人得到一张换餐叉券。
    • 饿了,把换餐叉券交给有餐叉的人,有餐叉的人吃饱了会把餐叉交给有券的人。有了券的人不会再得到第二张券。
    • 保证有餐叉的都有得吃。

    这个解法允许很大的并行性,适用于任意大的问题。

    一个没有高级趣味的人。 email:hushui502@gmail.com
  • 相关阅读:
    开启linux服务器防火墙
    Linux系统编程11_管道和命名管道
    Lua语法
    Git学习
    Buildroot介绍
    Makefile基本介绍
    页、页表和块
    文件系统,根文件系统,MTD
    什么是ioctl
    bootargs的mtdparts解析
  • 原文地址:https://www.cnblogs.com/CherryTab/p/12088495.html
Copyright © 2011-2022 走看看