Skip to content

2011年 408 操作系统 第 32 题

操作系统2011年选择题2分

题目

有两个并发执行的进程 P1 和 P2,共享初值为 1 的变量 x。P1 对 x 加 1,P2 对 x 减 1。加 1 和减 1 操作的指令序列分别如下所示。

C
P1 // 加 1 操作
load R1, x // 取 x 到寄存器 R1 中
inc R1
store x, R1 // 将 R1 的内容存入 x
P2 // 减 1 操作
load R2, x // 取 x 到寄存器 R2 中
dec R2
store x, R2 // 将 R2 的内容存入 x

两个操作完成后,x 的值( )。

错因

A

凑了"两次加"或"两次减"的极端值——但每次操作内部 inc / dec 只执行一次,最终结果不可能比初值大 2 或小 2。最终 x 的值由"最后一次 store 写入的值"决定,而每个 R 的范围是 0~2,store 不可能写出 -1 或 3。

B

把"互斥执行"和"交错执行"混了——只有当两个操作互斥执行(P1 完才 P2、或 P2 完才 P1)时,结果才一定是 1。题目说并发执行,没有互斥保护,指令可以交错,结果不止 1。"只能为 1"是假设了互斥但题面没说。

D

把 -1 也算进去——但分析下来 x 不会是 -1。即使最坏交错,store 写入的也只能是 R1(0/1/2 之一)或 R2(0/1/2 之一),最终值只可能是 0、1、2。把 -1 当作可能值是没仔细枚举每条指令的取值范围。

总解析

每个操作的内部指令是顺序的:

P1P2
load R1, xload R2, x
inc R1dec R2
store x, R1store x, R2

并发执行时两个操作的 6 条指令可以任意交错,但每个操作内部顺序保持。最终 x 值由最后一次 store 决定。

枚举可能结果

情况 1:完全串行(P1 全完再 P2,或反之)

  • P1 → P2:x: 1 → 2 → 1。最终 x = 1
  • P2 → P1:x: 1 → 0 → 1。最终 x = 1

情况 2:P1 store 后 P2 store(两边都 load 到 1,但 P1 先写)

  • P1 load R1=1 → inc R1=2 → store x=2
  • 然后 P2 load R2=1 → dec R2=0 → store x=0
  • 最终 x = 0

这种情况要 P2 的 load 在 P1 的 store 之后。

情况 3:P1 load 之后 P2 全完,再 P1 store(P1 用旧值覆盖 P2 的写)

  • P1 load R1=1 → P2 load R2=1 → P2 dec R2=0 → P2 store x=0 → P1 inc R1=2 → P1 store x=2
  • 最终 x = 2

情况 4:交错但都读到旧值

  • P1 load R1=1 → P2 load R2=1 → P1 inc → P2 dec → 两边各自 store
    • 若 P1 后 store:x = 2
    • 若 P2 后 store:x = 0

总结

交错模式x 最终值
串行(任一顺序)1
一边完后另一边读到新值(也是串行情况)1
两边都读到旧值 1,P2 后 store0
两边都读到旧值 1,P1 后 store2

可能值集合:{0, 1, 2}

为什么不可能是 -1 或 3

  • store 的值来自 R1 或 R2,范围分别是 [0, 2](R2 = 1-1=0;R1 = 1+1=2)
  • 两个寄存器都基于初始 x = 1 计算(最早只能 load 到 1,因为没人改过 x;中途 store 后另一方 load 才可能拿到 0 或 2)
  • 即使中途 store 改了 x,另一方再 load 拿到 0 或 2,也只能进一步算到 -1 或 3(dec(0)=-1, inc(2)=3)——但要让 P2 在 P1 store(x=2) 之后重新 load + dec,需要 P2 已经完成 load 再回去,但每个操作只 load 一次,不可能重新 load。所以 -1 / 3 排除。

最终答案是 C

最后更新:

⚠️ 这道题暂未配可视化,欢迎在 CodeBrick 反馈区告诉我们你想看哪道题