来自操作系统概念


5.8.2使用监视器的餐饮哲学家解决方案

接下来,我们通过展示无死锁来说明监视器的概念
解决餐饮哲学家的问题。此解决方案将
限制哲学家只有在两个人都拿起筷子的情况下
其中可用。要编写此解决方案的代码,我们需要区分
在我们可以找到一个哲学家的三个州中。为了这
目的,我们介绍以下数据结构:

enum {THINKING, HUNGRY, EATING} state[5];


哲学家我只能在她两个的情况下设置变量state[i] = EATING
邻居不吃饭:(state[(i+4) % 5] != EATING)
(state[(i+1) % 5] != EATING)

我们还需要声明

condition self[5];


这使哲学家i在饿了的时候就推迟了自己,但是
无法获得她需要的筷子。

monitor DiningPhilosophers
{

    enum {THINKING, HUNGRY, EATING} state[5];
    condition self[5];
    void pickup(int i) {

        state[i] = HUNGRY;
        test(i);
        if (state[i] != EATING)
            self[i].wait();

    }
    void putdown(int i) {

        state[i] = THINKING;
        test((i + 4) % 5);
        test((i + 1) % 5);

    }
    void test(int i) {

        if ((state[(i + 4) % 5] != EATING) &&
        (state[i] == HUNGRY) &&
        (state[(i + 1) % 5] != EATING)) {
            state[i] = EATING;
            self[i].signal();
        }

    }
    initialization code() {

        for (int i = 0; i < 5; i++)
            state[i] = THINKING;
    }

}


图5.18餐饮哲学家问题的监视器解决方案。

每个哲学家在开始吃饭之前,必须调用该操作
pickup()。此举可能导致哲学家被停职
处理。成功完成操作后,
哲学家可能会吃东西。此后,哲学家援引
putdown()操作。

DiningPhilosophers.pickup(i);
...
eat
...
DiningPhilosophers.putdown(i);


很容易证明,该解决方案可确保没有两个邻居
同时吃饭,不会发生僵局。

但是,我们注意到,哲学家可能会饿死
死亡。我们没有提出这个问题的解决方案,而是
把它留给你练习。


为什么显示器解决方案没有死锁?

哲学家为什么可能饿死?

该问题有什么解决方案?

谢谢。

最佳答案

要了解为什么两个邻居永远不能同时吃饭,请查看test(int i)方法。这是将哲学家的状态设置为EATING的唯一位置:

if ((state[(i + 4) % 5] != EATING) &&
    (state[i] == HUNGRY) &&
    (state[(i + 1) % 5] != EATING)) {
        state[i] = EATING;
        self[i].signal();
}


前面的if条件确保任何哲学家i的邻居(i + 4) % 5(i + 1) % 5都没有吃饭。

因为signal()不公平,所以可能会出现饥饿:它会随机唤醒任何等待的线程,因此可能不会在任意长时间内唤醒某个线程。

10-07 23:36