使用二进制信号量用餐哲学家
Posted
技术标签:
【中文标题】使用二进制信号量用餐哲学家【英文标题】:Dining philosophers using binary semaphores 【发布时间】:2018-01-21 06:06:42 【问题描述】:这个伪代码能否以最大并行度解决哲学家进餐问题?这里mutex
是一个初始化为1的二进制信号量。假设叉子的编号从0到(N-1)。从 0 到 (N-1) 共有 N 个哲学家。
void philosopher(int i) // ith philosopher
while (true)
think();
down(&mutex); // acquire lock
take_fork(i); // take left fork
take_fork((i+1)%N); // take right fork
up(&mutex); // release the lock
eat();
down(&mutex); // acquire lock
put_fork(i);
put_fork((i+1)%N);
up(&mutex); // release the lock
这应该以最大的并行度解决哲学家进餐问题,因为在一位哲学家获得两个分叉后,锁就会被释放。但会吗?会不会有活力的问题?我很困惑。
【问题讨论】:
当哲学家获得互斥体并发现他的右叉被占用时会发生什么?take_fork
会失败从而导致左叉未释放吗?
这应该是不可能的,因为互斥锁已经被其他哲学家关闭了。 @DmitriChubarov
【参考方案1】:
为了回答你的问题,我想提供一些似乎导致你的哲学家进入不受欢迎状态的事件。
考虑一个具有 N>2 个哲学家 Ph(0),...,Ph(N-1) 和以下动作序列的系统:
Ph(1).think();
Ph(0).think();
Ph(1).down(&mutex);
Ph(1).take_fork(1);
Ph(1).take_fork(2);
Ph(1).up(&mutex);
Ph(0).down(&mutex);
Ph(0).take_fork(0);
Ph(0).take_fork(1);
回想一下fork(1)
已经被Ph(1)
获取。现在根据take_fork()
的语义,可能会发生不同的行为。
如果无法获得分叉,take_fork()
立即失败,则永远不会释放 fork(0)
。
如果take_fork()
挂起直到资源被释放,那么互斥锁将永远不会被释放,其他哲学家都无法取得进展,因此一次只有一个哲学家在吃饭。
【讨论】:
以上是关于使用二进制信号量用餐哲学家的主要内容,如果未能解决你的问题,请参考以下文章