下面讨论Peterson算法,它是一个经典的基于软件的临界区问题(critical-section problem)的解决方案。

因为现在的计算机体系架构执行基本的机器指令,比如像load和store,Peterson算法在这些计算机上并不能确保正确运行。

Peterson算法适用于两个进程在临界区剩余区之间交替执行。两个进程分别为P0和P1。为了方便起见,当使用Pi时候,我们使用Pj来表示其他进程,j = 1 - i.

Peterson算法需要这两个进程之间共享两个数据项:

int turn;
boolean flag[2];

变量turn指示轮到谁进入它的临界区了。当turn = i,那么Pi允许在其临界区中执行。

数组变量flag被用于指示进程是否准备好进入其临界区。当flag[i] = true,这个值表示的是Pi进程已经准备好进入其临界区。

为了进入临界区,进程Pi首先将flag[i]设置为true,并将turn的值设置为j,从而声明如果另一个进程Pj希望进入临界区,那么Pj能进入。而如果这两个进程同时打算进入其临界区,那么turn会几乎在同时设置成i和j。这些任务中只有一个会持续下去;另一个会发生,但会立即被覆盖。turn的最终值决定了两个进程中的哪一个被允许率先进入它的临界区。

我们现在证明这个算法是正确的。我们需要证明:

  1. 互斥成立。

  2. 满足进入(progress即不死锁)需求

  3. 满足限界等待需求

证明1:

Pi进程只有在flag[j] == false或者turn == i时候才会进入临界区。

如果两个进程同时在其临界区内执行,那么flag[0] = flag[1] = true .

但是turn的值只能是0或者1,所以P0和P1同一时间不能成功地执行它们的while语句。因此只能有一个进程(如Pj)能成功的执行完while语句,而另一个进程(Pi)则至少必须执行一个附加的语句("turn = j")。

而且,由于只要Pj在其临界区内,flag[j] = true和turn = j就会同时成立。

互斥成立

证明2:

只要flag[j] = true && turn = j成立,进程Pi陷入while循环语句.

如果Pj不准备进入临界区,那么flag[j] = false,Pi就可以进入临界区

如果Pj已经设置flag[j] = true,且也在其while语句中执行,那么turn = j 或者 turn = i.如果turn = i,那么Pi进入临界区;如果turn = j,那么Pj进入临界区。然而当Pj退出临界区,它会设置flag[j] = false,以允许Pi进入其临界区

如果Pj重新设置flag[j] = true,那么它也必须设置turn为i.

因此由于进程Pi执行while语句时并不改变turn的值,所以Pi会进入临界区(证明2成立),并且Pi最多在Pj进入临界区一次后就能进入(证明3成立)

results matching ""

    No results matching ""