关于我的睡眠理发师和就餐哲学家算法的正确性的提示(不是答案)?
我正在上操作系统课程。两周后我们有一次考试,我怀疑那里有哲学家就餐和理发师睡觉的问题(信号量版本)。现在,如果我愿意,我可以打开教科书并得到答案,但我宁愿自己实际学习它们。我花了一些时间来解决这些问题,我想我已经接近解决问题了,但是......我不确定。我不想只是被告知我的解决方案到底有什么问题,但我想要提示。我想尽可能地自己弄清楚。
所以,睡觉的理发师...在我制定的解决方案中,我有三个二进制信号量:“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
我不确定我是否走在正确的轨道上......我看到的问题是,当没有客户时,理发师就走了但是,当新顾客到来时,他可能还没有完全睡着,所以顾客会去等候室永远等他。我想到了几种可能的方法来解决这个问题......我可以在理发师睡觉前设置一个标志(使用信号量来访问它),然后新客户可以检查它,然后坐在紧密循环直到理发师完全睡着,然后叫醒他......但这并不是最好的解决方案,不是吗?我对此很不确定...有什么提示吗?再说一遍,我不想要直接的答案,我想要提示。
现在哲学家就餐问题……我对这个问题更有信心了,但我仍然想仔细检查一下。在我制定的解决方案中,我有一个用于抓住一双筷子的二进制信号量“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);
我可以看到的一个问题是,如果一个哲学家正在吃饭,而他旁边的人试图抓住一双筷子,他将无法获得一双完整的筷子,因此每个人都会被冻结,直到当前的吃者吃完。我走在正确的轨道上吗?
我将非常感谢任何反馈!
真挚地, 红区
I'm in an operating systems course. We have an exam in two weeks, and I suspect that the dining philosopher and sleeping barber problems (semaphore versions) are in there. Now, if I wanted to, I could just crack open the textbook and have the answers spoonfed to me, but I would rather actually learn them on my own. I've spent some time working through the problems and I think I'm getting close, but... I'm not sure. I don't want to just be told exactly what's wrong with my solutions, but I would like hints. I want to figure out as much as possible by myself.
So, sleeping barber... In the solution I've worked out I have three binary semaphores: 'w' for the waiting room, 'c' for the barber's chair, and 'x' for exit. The barber can take care of one customer at a time, when done checks the waiting room for other customers, and if there are none, sleeps, right? This is what I have worked out for the barber process's code (in kinda a hybrid of C and pseudocode):
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.
}
I think this is right but I'm not sure. I feel like the customer who just came in should be handled by the code in the while(customersWaiting > 0) loop, but I can't figure out how to arrange the semaphores to make that work.
The customer, if I understand it, must check to see if the chair is occupied. If it is, he must see if it is the barber in it. If it is, me wakes him up, otherwise he sits in the waiting room. If the waiting room is full, he leaves, right? Anyway, here's the code I've worked out for the customer process:
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
I'm not sure if I'm on the right track here or not... the problem I see is that, when there are no customers, the barber goes to sleep but, he might not be all the way asleep when a new customer arrives, and so the customer will go to the waiting room and wait for him forever. I've thought of a couple possible ways to solve this...I could have a flag that the barber sets right before he sleeps (using a semaphore to access it), and then the new customer could check that, and sit in a tight loop until the barber is all the way asleep, then wake him up... but that's not exactly the best solution, is it? I'm so unsure about this... Any hints? Again I don't want the answer straight up, I want hints.
Now the dining philosophers problem... I'm significantly more confident about this one, but I still want to double check. In wthe solution I've worked out, I have a binary semaphore 'g' for grabbing a pair of chopsticks, a counting semaphore 'a' for the number of philosophers that may start eating, and one binary semaphore c[0..n-1] for each chopstick. Basically, half the philosophers (rounded down, of course) may eat at any one time, right? (rounded down, of course) So in my solution, the philsopher after his thinking is done tries to grab a pair of chopsticks chopstick, but only if less than half the philosophers are eating and no one else is trying to grab a chopstick. I've coded the philosopher's code like this:
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);
The one problem I can see is that, if a philosopher is eating and someone adjacent to him tries to grab a pair of chopsticks, he won't be able to get a full pair and therefore everyone will be frozen until the current eater finishes. Am I on the right track at all here?
I would greatly appreciate any feedback!
Sincerely,
RedZone
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
哲学家就餐是一个通过锁排序解决的经典死锁问题(我确信这在你的书中,尝试代码很好,但最好先有基础)
您可以将相同的逻辑应用于大多数死锁问题。这类问题的重点不在于如何编写解决方案,而是要认识到它所说明的问题(死锁、资源匮乏)、解决方案,然后将该解决方案应用于其他更普遍的此类问题(在具有锁A、B、C,如何保证尝试获取多个锁的线程之间不出现死锁(其中筷子是锁的隐喻,哲学家是线程或进程的隐喻))。
Dining philosophers is a classical deadlock problem solved by lock ordering (I am sure that this is in your book, trying out code is nice, but it is nice to have the foundations first)
You can apply the same logic to most deadlock problems. The point to this type of problem is not how to code a solution, but to recognize the problem it illustrates (deadlock, resource starvation), the solution, and then apply the solution to other more generalized problems of this type (in a program with locks A, B and C, how to ensure that there is no deadlock between threads trying to acquire multiple locks (where chopsticks are a metaphor for locks and philosophers are a metaphor for threads or processes)).
您读过关于这些的维基百科文章吗?您有具体问题吗?我很高兴你想自己解决这些问题,但这是一个糟糕的计划。看看存在什么洞察力。维基百科并不经常给你灌输,而是给你一个基础。
是的,你走在正确的道路上。注意,两个人可以同时吃饭,但不能多吃。诀窍是,在你拿起它之后,如果你拿不到第二个,就把你拿着的那个放下几格。
所有伪代码往往都是 C 的混合;)
Have you read the wikipedia articles on each of these? Do you have specific questions from there? I'm glad you want to work them out for yourself, but that's a bad plan. See what insight exists. Wikipedia doesn't often spoonfeed you, but gives you a foundation.
You're on the right track, yes. Note that it's possible for two people to eat at the same time, but no more. The trick is after you pick it up, if you can't get the second one, put down the one that you are holding for a few ticks.
all pseudocode tends to be a hybrid of C ;)