这种互斥伪代码如何工作?

时间:2017-09-07 02:59:41

标签: c

bool flag[2] = {false, false}
process p(i):   // i in { 0, 1 }
while (flag[1-i]) {
    // do nothing
}
flag[i] = true
while (flag[1-i]) {
    // do nothing
}
<critical section>
flag[i] = false

这段代码让我发疯。它是为解决两个程序(0,1)之间的互斥而构建的代码。 有人可以解释一下,当放入代码时,每个程序0和1的标志如何变化。

1 个答案:

答案 0 :(得分:0)

2个布尔值flag的数组必须位于共享内存中才能有效。对于流程而言,这至关重要;如果这些是线程,那么你不需要共享内存。

最初,进程0或1都没有将其flag值设置为true

假设进程i = 0尝试访问关键部分。第一个忙循环(while循环)等待flag[1]false(此时它为假);然后代码集flag[0] = true。代码现在进入第二个忙循环; flag[1]仍为false,因此它会继续安全地进入关键部分,因为知道其他进程也不在关键部分。

假设当进程0处于临界区时,进程1也尝试输入它。它在第一个忙循环中被阻止,因为flag[0]为真。它仍然是这样,直到进程0离开并将flag[0]设置为false。当进程0离开时,进程1将flag[1]设置为true,进入第二个busy循环,然后离开,因为flag[0]为false;它现在处于关键部分。

为什么两个忙循环?因为两个进程可能同时在多个核上运行,并且两者都可能同时进入第一个繁忙的循环。他们都会看到另一个标志是假的,退出循环并将自己的标志设置为true,并重新检查其他标志是否仍为假。大多数时候,其中一个人会看到其他人是假的并且会进入关键部分。偶尔,他们可能都发现其他人是真的(因为他们在锁定步骤中工作太多了),然后两者都会进入第二个忙循环,并且都不会退出 - 死锁。

所以,我并不相信代码是一个万无一失的互斥机制,尽管它需要运气不好才能陷入僵局。但是,如果有足够的尝试,就会出现运气不好的情况 - 长期运行的流程无法承担风险。