操作系统中的进程同步:Peterson算法详解
字数 1414 2025-11-29 22:52:06

操作系统中的进程同步:Peterson算法详解

1. 问题背景:临界区问题
在多进程/多线程环境中,当多个执行流需要访问共享资源(如变量、数据结构等)时,可能会因为交替执行导致数据不一致,这就是临界区问题。我们需要一种机制确保:

  • 互斥:同一时刻只有一个进程能进入临界区。
  • 进展:如果没有进程在临界区内,那么需要进入临界区的进程能够进入。
  • 有限等待:进程从申请进入临界区到获准进入的等待时间是有限的。

2. Peterson算法的基本思想
Peterson算法是一种经典的软件解决方案,用于两个进程/线程之间的同步。它不需要特殊的硬件指令(如Test-and-Set),仅通过共享变量来实现互斥。其核心思想是"礼貌谦让":

  • 每个进程都先表达自己想进入临界区的意愿。
  • 然后指定另一个进程为"优先者"。
  • 只有当对方不想进入,或者对方指定我为优先时,我才能进入。

3. 算法所需的共享变量

  • int turn; // 表示当前轮到哪个进程进入(0或1)
  • bool flag[2]; // 表示进程是否想进入临界区(flag[0]对应进程0,flag[1]对应进程1)

4. 算法的详细步骤
假设有两个进程P0和P1(其ID分别为0和1)。

进程Pi(i为0或1)的代码:

while (true) {
    // 1. 表达进入意愿
    flag[i] = true;
    
    // 2. 指定对方为优先者
    turn = j;  // j是另一个进程的ID(1-i)
    
    // 3. 谦让检查:只有当对方不想进入,或者对方指定我优先时,我才能进入
    while (flag[j] == true && turn == j) {
        // 忙等待(busy-waiting)
    }
    
    // 4. 进入临界区
    // ... 访问共享资源 ...
    
    // 5. 离开临界区
    flag[i] = false;
    
    // 6. 剩余区代码
    // ...
}

进程Pj(j=1-i)的代码对称。

5. 逐步解析算法逻辑

  • 步骤1(flag[i]=true):进程Pi明确表示"我想进入临界区"。
  • 步骤2(turn=j):Pi礼貌地说"你先请",将优先权让给Pj。
  • 步骤3(while条件检查)
    • 如果Pj不想进入(flag[j]==false),Pi直接进入临界区。
    • 如果Pj也想进入(flag[j]==true),则检查turn的值:
      • 如果turn==j(确实轮到Pj),Pi循环等待。
      • 如果turn==i(实际上轮到Pi),Pi进入临界区。

6. 为什么能保证互斥?
假设P0和P1同时试图进入临界区:

  • 它们都会设置自己的flag为true。
  • 最后执行turn=语句的进程将决定turn的最终值。
  • 由于turn只能是0或1,只有一个进程能通过while条件检查:
    • 如果turn最终为0,P0看到turn==0(自己)而通过检查,P1看到turn==0(对方)而等待。
    • 如果turn最终为1,P1通过检查,P0等待。

7. 为什么能保证进展和有限等待?

  • 进展:如果没有进程在临界区,想进入的进程不会被阻止。
  • 有限等待:当进程Pi离开临界区时,它会设置flag[i]=false,这会立即释放Pj的等待(如果Pj在等待)。如果Pj在Pi之后表达意愿,turn的值会确保其中一个进程能进入。

8. 算法的局限性

  • 仅适用于两个进程:Peterson算法不能直接扩展到多个进程。
  • 忙等待:等待的进程会持续检查条件,浪费CPU资源。
  • 内存屏障问题:在现代多核处理器上,需要内存屏障确保flag和turn的修改对其他核心立即可见。

9. 实际应用
虽然Peterson算法本身很少直接用于生产环境(因有更高效的硬件指令如CAS),但它:

  • 是理解同步问题的经典教学案例。
  • 展示了如何用纯软件实现互斥。
  • 为更复杂的同步机制提供了理论基础。

通过这个逐步分析,你应该能理解Peterson算法如何巧妙地利用两个共享变量,在不需要硬件支持的情况下解决两个进程的临界区问题。

操作系统中的进程同步:Peterson算法详解 1. 问题背景:临界区问题 在多进程/多线程环境中,当多个执行流需要访问共享资源(如变量、数据结构等)时,可能会因为交替执行导致数据不一致,这就是 临界区问题 。我们需要一种机制确保: 互斥 :同一时刻只有一个进程能进入临界区。 进展 :如果没有进程在临界区内,那么需要进入临界区的进程能够进入。 有限等待 :进程从申请进入临界区到获准进入的等待时间是有限的。 2. Peterson算法的基本思想 Peterson算法是一种经典的 软件解决方案 ,用于两个进程/线程之间的同步。它不需要特殊的硬件指令(如Test-and-Set),仅通过共享变量来实现互斥。其核心思想是"礼貌谦让": 每个进程都先表达自己想进入临界区的意愿。 然后指定另一个进程为"优先者"。 只有当对方不想进入,或者对方指定我为优先时,我才能进入。 3. 算法所需的共享变量 int turn; // 表示当前轮到哪个进程进入(0或1) bool flag[2]; // 表示进程是否想进入临界区(flag[ 0]对应进程0,flag[ 1 ]对应进程1) 4. 算法的详细步骤 假设有两个进程P0和P1(其ID分别为0和1)。 进程Pi(i为0或1)的代码: 进程Pj(j=1-i)的代码对称。 5. 逐步解析算法逻辑 步骤1(flag[ i]=true) :进程Pi明确表示"我想进入临界区"。 步骤2(turn=j) :Pi礼貌地说"你先请",将优先权让给Pj。 步骤3(while条件检查) : 如果Pj不想进入(flag[ j ]==false),Pi直接进入临界区。 如果Pj也想进入(flag[ j ]==true),则检查turn的值: 如果turn==j(确实轮到Pj),Pi循环等待。 如果turn==i(实际上轮到Pi),Pi进入临界区。 6. 为什么能保证互斥? 假设P0和P1同时试图进入临界区: 它们都会设置自己的flag为true。 最后执行 turn= 语句的进程将决定turn的最终值。 由于turn只能是0或1, 只有一个进程 能通过while条件检查: 如果turn最终为0,P0看到turn==0(自己)而通过检查,P1看到turn==0(对方)而等待。 如果turn最终为1,P1通过检查,P0等待。 7. 为什么能保证进展和有限等待? 进展 :如果没有进程在临界区,想进入的进程不会被阻止。 有限等待 :当进程Pi离开临界区时,它会设置flag[ i ]=false,这会立即释放Pj的等待(如果Pj在等待)。如果Pj在Pi之后表达意愿,turn的值会确保其中一个进程能进入。 8. 算法的局限性 仅适用于两个进程 :Peterson算法不能直接扩展到多个进程。 忙等待 :等待的进程会持续检查条件,浪费CPU资源。 内存屏障问题 :在现代多核处理器上,需要内存屏障确保flag和turn的修改对其他核心立即可见。 9. 实际应用 虽然Peterson算法本身很少直接用于生产环境(因有更高效的硬件指令如CAS),但它: 是理解同步问题的经典教学案例。 展示了如何用纯软件实现互斥。 为更复杂的同步机制提供了理论基础。 通过这个逐步分析,你应该能理解Peterson算法如何巧妙地利用两个共享变量,在不需要硬件支持的情况下解决两个进程的临界区问题。