彼得森的算法是否满足饥饿?

时间:2010-10-27 13:26:25

标签: algorithm deadlock solution

我一直在搜索关于Peterson's algorithm的信息,但是已经发现了一些参考文献,说明它不满足饥饿但只是死锁。这是真的?若有,有人可以详细说明为什么不呢?

彼得森的算法:

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;

算法使用两个变量,flag和turn。标志值为1表示进程想要进入临界区。变量turn保存转过程的ID。如果P1不想进入其临界区,或者如果P1通过将转到0设置为优先于P0,则允许进程P0进入临界区。

3 个答案:

答案 0 :(得分:9)

正如Ben Jackson所怀疑的那样,问题在于广义算法。标准的2过程Peterson算法满足无饥饿特性。

显然,彼得森的原始论文实际上有N处理器的算法。这是我刚刚用C ++语言编写的草图,据说是这个算法:

// Shared resources
int pos[N], step[N];

// Individual process code
void process(int i) {
    int j;
    for( j = 0; j < N-1; j++ ) {
        pos[i] = j;
        step[j] = i;
        while( step[j] == i and some_pos_is_big(i, j) )
            ; // busy wait
    }
    // insert critical section here!
    pos[i] = 0;
}

bool some_pos_is_big(int i, int j) {
    int k;
    for( k = 0; k < N-1; k++ )
        if( k != i and pos[k] >= j )
            return true;
    }
    return false;
}

这是N = 3的死锁情景:

  • 首先启动流程0,设置pos[0] = 0step[0] = 0,然后等待。
  • 过程2接下来开始,设置pos[2] = 0step[0] = 2,然后等待。
  • 流程1从最后开始,设置pos[1] = 0step[0] = 1,然后等待。
  • 第一个进程2是第一个注意到step[0]中的更改,因此设置了j = 1pos[2] = 1step[1] = 2
  • 进程0和1被阻止,因为pos[2]很大。
  • 过程2未被阻止,因此设置j = 2。它从for循环中逃脱并进入临界区。完成后,它会设置pos[2] = 0,但会立即再次开始竞争关键部分,从而设置step[0] = 2并等待。
  • 流程1是第一个注意到step[0]中的更改并在此之前继续进行的流程。
  • ...
  • 流程1和2轮流竞争流程0。

参考。所有细节均来自Alagarsamy的论文“Some myths about famous mutual exclusion algorithms”。显然Block和Woo在“A more efficient generalization of Peterson's mutual exclusion algorithm”中提出了一个确实满足无饥饿的修改算法,Alagarsamy后来在“A mutual exclusion algorithm with optimally bounded bypasses”中得到了改进(通过获得最佳饥饿界限N-1)。 / p>

答案 1 :(得分:2)

雷克斯的死锁情况有问题 (作为旁注:正确的术语是饥饿场景,因为对于死锁,至少有两个线程需要被“卡住”才能看到维基百科:deadlockstarvation

当进程2和1进入级别0时,步骤[0]被设置为1或2,从而使进程0的提前条件为假,因为step[0] == 0为假。

2个过程的peterson算法稍微简单一些,可以防止饥饿。

n个过程的peterson算法要复杂得多

如果某个过程匮乏条件step[j] == i and some_pos_is_big(i, j),则必须永远为真。这意味着没有其他进程进入同一级别(这将使step[j] == i为false)并且至少一个进程始终与i处于同一级别或更高级别(以保证some_pos_is_big(i, j)是保持真实)

此外,只有一个进程可以在此级j中死锁。如果两个人陷入僵局,那么其中一人step[j] == i将是假的,因此不会陷入僵局。 因此,这意味着任何流程都无法进入同一级别,并且必须始终存在上述级别的流程。

由于没有其他进程可以加入上述进程(因为它们无法进入j级,因此不能超过lelel j)至少有一个进程必须死锁,或者临界区中的进程不会释放关键部分。

如果我们假设临界区中的进程在有限时间后终止,那么上述进程中只有一个必须是死锁的。

但是对于那个陷入僵局的人来说,上面的另一个必须陷入僵局等等。 但是,上面只有有限的过程,因此最终的过程不会陷入僵局,因为一旦关键部分被释放,它就会前进。

因此n进程的peterson算法可以防止饥饿!

答案 2 :(得分:0)

我怀疑关于饥饿的评论是关于一些广义的,N过程的彼得森算法。有可能构造一个有限等待的N过程版本,但没有特别讨论我们不能说为什么特定的泛化可能会受到饥饿。

快速Google出现了this paper,其中包括伪代码。如您所见,通用版本要复杂得多(而且价格昂贵)。