Skip to content

2010年 408 操作系统 第 27 题

操作系统2010年选择题2分

题目

进程 P0 和 P1 的共享变量定义及其初值为

C
boolean flag[2];
int turn = 0;
flag[0] = FALSE;
flag[1] = FALSE;

若进程 P0 和 P1 访问临界资源的类 C 伪代码实现如下:

C
void P0() {
    while (TRUE) {
        flag[0] = TRUE;
        turn = 1;
        while (flag[1] && (turn == 1));
        临界区;
        flag[0] = FALSE;
    }
}
C

void P1() {
    while (TRUE) {
        flag[1] = TRUE;
        turn = 0;
        while (flag[0] && (turn == 0));
        临界区;
        flag[1] = FALSE;
    }
}

则并发执行进程 P0 和 P1 时产生的情形是( )。

错因

A

把"两进程都举手 + while 等"误以为是死锁式忙等。但本算法(Peterson)两个 while 条件不可能同时成立——turn 只能是 0 或 1,最多让一方等而另一方进。互斥保证是有的,把它否定就错了。

B

承认"不互斥"+"不饥饿"是双错。本算法明确互斥(设计目标就是互斥),且因为 turn 字段会被对方主动让出,两边轮流进,不会饥饿。

C

承认互斥但说会饥饿——但 Peterson 算法的核心特性就是有限等待:即使 P0 迅速 release 后又想再进、和 P1 抢 turn,turn 是被对方设置为对方让位(P0 设 turn=1、P1 设 turn=0),最多让一方再等一轮就一定能进。

总解析

这正是经典的 Peterson 算法——双进程互斥的软件解法。每个进程"先举手 + 让位 + 等":

c
flag[i] = TRUE;          // 我想进
turn = j;                // 但优先让对方
while (flag[j] && turn == j);  // 等:只有对方也想进且这一轮归对方时才等
// 临界区
flag[i] = FALSE;         // 离开,放下手

互斥性证明(反证):

假设 P0 和 P1 同时进入临界区——意味着两个 while 条件都不成立。

  • 对 P0:flag[1] && turn == 1 不成立 → flag[1] = FALSE 或 turn ≠ 1
  • 对 P1:flag[0] && turn == 0 不成立 → flag[0] = FALSE 或 turn ≠ 0

两人都举了手 → flag[0] = TRUE 且 flag[1] = TRUE。所以必须 turn ≠ 1 turn ≠ 0——这不可能(turn 只取 0 或 1)。矛盾,不可能同时进入。✓ 互斥成立。

无饥饿性证明

假设 P0 在 while 循环中等:意味着 flag[1] && turn == 1。这时如果 P1 进入临界区且不再进入(出来后 flag[1] = FALSE),P0 立刻能进。

如果 P1 出去后又想进:P1 重新执行 flag[1] = TRUE; turn = 0;——P1 会把 turn 设成 0 让位。这时 P0 的 while 条件 flag[1] && turn == 1 因 turn 变 0 而不成立,P0 立刻能进。

关键:每次进入前都设 turn = 对方 是 Peterson 的核心——它保证如果两人同时争,后到达 turn 赋值的那个让位(写后覆盖了对方的赋值),先 turn 设的人先进。这避免了任何一方被无限制阻塞。

逐项核对:

选项互斥?饥饿?判定
A不互斥 + 饥饿
B不互斥 + 不饥饿
C互斥 + 饥饿
D互斥 + 不饥饿

最终答案是 D

最后更新:

🎬 可视化演示
加载中...

提示:可在可视化区直接操作播放、步进、修改参数