为什么餐饮哲学家的监控解决方案没有僵局而是饥饿?

时间:2017-10-23 04:07:46

标签: concurrency operating-system synchronization monitor livelock

来自操作系统概念

  

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];
     

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

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);
     

很容易证明这个解决方案确保没有两个邻居   同时进食并且不会发生死锁

     

然而,我们注意到,哲学家可能会饿死   死亡即可。我们不提供解决此问题的方法而是   把它作为锻炼给你。

为什么监控解决方案没有死锁?

为什么哲学家可能会饿死?

这个问题的解决方案是什么?

感谢。

1 个答案:

答案 0 :(得分:2)

要理解为什么两个邻居永远不能同时进食,请查看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都不吃饭。

Starvation是可能的,因为signal()不公平:它会随机唤醒任何等待的线程,因此可能不会长时间唤醒某个线程。