我正在上操作系统类(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,如何确保尝试获取多个锁的线程之间没有死锁(筷子是锁的隐喻,哲学家是线程或进程的隐喻)。