我正在上操作系统类(class)。我们将在两周内进行一次考试,我怀疑那里有餐饮哲学家和熟睡中的理发师问题(信号量版本)。现在,如果我愿意的话,我可以打开教科书,然后把答案一字不漏地传给我,但我宁愿自己真正地学习它们。我花了一些时间解决这些问题,但我想我已经接近了,但是...我不确定。我不想仅仅被告知我的解决方案到底出了什么问题,但我想提出一些提示。我想自己弄清楚。

因此,睡着理发师...在我制定的解决方案中,我有三个二进制信号量:“w”代表候诊室,“c”代表理发师的椅子,“x”代表退出。理发师一次可以照顾一位顾客,做完之后再检查其他顾客的候诊室,如果没有,睡个好觉,对吗?这是我为理发程序代码(某种程度上是C和伪代码的混合)得出的结果:

while(true)
{
    P(w);    //Guarantees an entering customer can't check the waiting room before the barber.
    P(c);
    P(x);    //A customer being serviced can't leave until barber is done servicing him.
    while( customersWaiting > 0 )
    {
        V(c);    //Allow a waiting room customer to sit in barber's chair.
        V(w);    //Allow another customer to enter the waiting room
        service customer
        V(x);    //Allow customer to leave
        P(w);    //Lock waiting room so barber can check it.
    }
    //No customers
    V(w);   //Allow next entering customer to check waiting room.
    sleep
    V(c);   //Allows new customer service.
    service customer
    V(x);    //Allow customer to leave.
}

我认为这是正确的,但我不确定。我觉得刚进入的客户应该由while(customersWaiting> 0)循环中的代码处理,但是我不知道如何安排信号量以使其正常工作。

如果我理解的话,客户必须检查椅子是否被占用。如果是这样,他必须查看它是否是理发师。如果是这样,我叫醒他,否则他坐在候诊室。如果候车室已满,他会离开,对吧?无论如何,这是我为客户流程制定的代码:
P(w);    //Guarantees neither barber nor other customers can check waiting room.
if (chair is occupied)  //Could you write this as if(c), or would you create a separate flag?
{
    if (barber is sleeping)
    {
        wakeup barber
        V(w);    //Now the waiting room can be checked by someone else.
        P(c);    //Sit in barber's chair
        P(x);    //Attempt to exit shop
    }
}
else
{
    if (customersWaiting < amountOfChairs)
    {
        customersWaiting++;
        V(w);    //Now the waiting room can be checked by someone else.
        P(c);    //Sit in barber's chair, when it's available that is.
        P(x);    //Attempt to exit shop
        customersWaiting--;
    }
}
exit shop

我不确定我是否在正确的轨道上...我看到的问题是,当没有顾客时,理发师会休眠,但是当他刚来时,他可能不会一直睡着客户到达,因此客户将前往候诊室并永远等待他。我想过几种可能的方法来解决这个问题...我可能会有一个标志,理发师就在他 sleep 之前就设置了该标志(使用信号量对其进行访问),然后新客户可以检查一下,然后坐在直到理发师完全休眠,然后叫醒他……这并不是最好的解决方案,不是吗?我对此不太确定...有任何提示吗?再次,我不想直接回答,我想要提示。

现在餐饮哲学家的问题……我对此更加有信心,但我仍然想再三确认一下。在我已经解决的解决方案中,我有一个用来抓一双筷子的二进制信号量“g”,一个可以开始进食的哲学家数量的计数信号量“a”,以及一个二进制信号量c [0..n -1]。基本上,一半的哲学家(当然是四舍五入的人)可以一次吃东西,对吗? (当然,四舍五入)因此,在我的解决方案中,哲学家完成思想后,将尝试捕获一双筷子筷子,但前提是只有少于一半的哲学家在吃东西,并且没有其他人在尝试捕获筷子。我已经这样编码了哲学家的代码:
while(true)
{
    think
    P(g);    //Above all, no one else can try to grab a chopstick at the same time as someone else.
    P(a);    //Decrement the amount of philosophers that may start eating.
    P(c[left chopstick's number]);
    take left chopstick
    P(c[right chopstick's number]);
    take right chopstick
    V(g);    //Now someone else may attempt to grab a pair.
    eat
    V(c[left chopstick's number]);
    replace left chopstick
    V(c[right chopstick's number]);
    replace right chopstick
    V(a);

我能看到的一个问题是,如果一个哲学家在吃饭,而与他相邻的某人试图捕获一双筷子,他将不能拿一双完整的筷子,因此所有人都将被冻结,直到当前的食者吃完为止。我在这里的一切都正确吗?

我将不胜感激任何反馈!

真挚地,
红区

最佳答案

进餐哲学家是一个经典的死锁问题,可以通过锁排序解决(我相信这在您的书中,尝试代码是不错的选择,但是首先拥有基础是不错的选择)

  • 每个筷子都按一个(不同的)数字订购。
  • 哲学家必须能够拾起编号较低的筷子,然后才能拾起编号较高的筷子。
  • 放下编号较低的筷子后,即使无法立即获得编号较高的筷子,也可以捕获它。
  • 一个(可能是两个)哲学家将总是能够进食,并且最终会吃完,允许另一个(或两个)进食。

  • 1点2

    o

    4点3

    您可以将相同的逻辑应用于大多数死锁问题。这类问题的关键不是如何编写解决方案,而是要认识到它说明的问题(僵局,资源匮乏),解决方案,然后将解决方案应用于其他此类更普遍的问题(在具有锁A,B和C,如何确保尝试获取多个锁的线程之间没有死锁(筷子是锁的隐喻,哲学家是线程或进程的隐喻)。

    10-08 01:56