我有一个场景要讨论Peterson算法:
flag[0] = 0;
flag[1] = 0;
turn;
P0: flag[0] = 1;
turn = 1;
while (flag[1] == 1 && turn == 1)
{
// busy wait
}
// critical section
...
// end of critical section
flag[0] = 0;
P1: flag[1] = 1;
turn = 0;
while (flag[0] == 1 && turn == 0)
{
// busy wait
}
// critical section
...
// end of critical section
flag[1] = 0;
假设两个进程同时开始执行.P0设置flag [0] = 1并且死掉。然后P1开始。它的while条件将满足为flag [0] = 1(由P0和turn = 0设置)并且它将永远卡在此循环中,这是一个死锁。
彼得森算法也没有考虑到这种情况吗?
如果在分析此类算法时不考虑过程中的死亡,那么在William Stalling的操作系统手册中,附录A包含一系列并发算法,从4个不正确的算法开始演示。通过在完成之前考虑过程死亡(除了其他情况)但是然后声称Peterson算法是正确的,它证明它们是不正确的。
我遇到了this线程,它让我知道在考虑N进程(n> 2)时存在问题但是对于两个进程这个算法工作正常。
那么算法的分析是否有问题(由我的一个同学建议,我完全是他的第二个),如上所述,或者Peterson算法也没有声称死锁是否也有2个进程?
在本文Some myths about famous mutual exclusion algorithms中,作者得出结论彼得森从未声称他的算法确保有限绕过。
无限绕行可以被认为是无限的,就像死锁一样?那么在这种情况下,我们可以减少接受Peterson算法可能导致死锁的麻烦。
答案 0 :(得分:10)
当然,您可以编写会抛出未处理异常的代码,但算法假设执行进程在其临界区执行后始终将其标志设置为false。因此,彼得森的算法确实通过了关键部分的3次测试。
1)相互排斥 - flag [0]和flag [1]都可以为true,但turn只能是0或1.因此,只能执行两个关键部分中的一个。另一个会旋转等待。
2)进度 - 如果进程0在临界区,则转= 0并且标志[0]为真。一旦它完成了它的关键部分(即使发生灾难性事件),它必须将flag [0]设置为false。如果进程1是旋转等待,它现在将自由为标志[0]!=真。
3)绑定等待 - 如果进程1正在等待,则进程0只能进入一次临界区,然后在进程1发出绿灯之前,如#2中所述。
彼得森算法的问题在于,在现代架构中,CPU缓存可能会破坏互斥要求。该问题称为缓存一致性,并且CPU 0上的进程0使用的高速缓存可能将flag [0]设置为等于true,而CPU 1上的进程1仍然认为flag [0]为false。在这种情况下,两个关键部分都会进入,并且BANG ......相互排斥失败,现在可以进行竞争条件。
答案 1 :(得分:4)
你是对的,彼得森的算法假设在执行同步算法的一部分时进程不会失败。我无法访问您提到的那本书,但也许其他算法不正确,因为它们没有说明在同步部分之外失败的进程(哪个更糟)?
注意:虽然历史上仍然有趣,但彼得森的算法也对内存工作的方式做出了假设,这些假设在今天的硬件上是无效的。
答案 2 :(得分:3)
大多数锁定算法都没有考虑到在临界区内死亡的过程(其他过程如何区分锁定后死亡的过程与仅需要很长时间的过程?)。 p>
但是,如果某个进程在关键部分不时死亡,则不应阻止其他进程进入或离开。例如,两个过程“轮流”进入临界区的关键部分是有问题的;如果一个进程在临界区之外死亡,则第二个进程永远等待第一个进程转向。这可能是你老师所指的。
(作为一个hacky解决方案,你可以尝试处理在一个关键部分死亡的进程超时;如果一个进程需要很长时间,你会认为它已经死了。这样就有可能让两个进程进入关键部分但是,这需要太长时间。)
答案 3 :(得分:3)
如果我们假设过程中的过早死亡(尝试生产者/消费者问题),甚至一些信号量方法也会失败 所以,我们不能说算法是不正确的,只是因为它不是为了我们所看到的目的而制作的。这些都是误解的。
答案 4 :(得分:1)
我同意法比奥。而不是说'#34; P0设置标志[0] = 1并且死",我想考虑调度程序 P0被抢占的情况,并且在P0集之后立即安排P1其标志[0]至1.
然后两个进程都陷入忙碌的等待状态,如下:
标志(0)= 1,标志(1)= 1并且转= 0。 这意味着P1将忙于等待while循环中的条件为真。
现在如果P1被抢先,让我们说由于超时而P0由调度程序安排,然后: 标志(0)= 1,标志(1)= 1并且转= 1。 这意味着P0也会忙着等待条件为while。
现在两个进程都在忙着彼此等待并发生死锁。 我不知道为什么这个解决方案如此着名或者我们错过了什么......?