内存一致性、原子操作与乱序执行基础

共 44 题
#

1. acquire/release 语义与完整 memory fence 各自约束哪些重排,为何前者通常开销更低?

A release 约束之后的操作
B acquire 约束两侧重排
C 完整 fence 与 acquire 开销相同
D acquire 约束之后不重排到之前,release 约束之前不重排到之后,各是一侧,开销低于双向完整 fence ✓ 正确答案
#

2. store-store 与 load-load 重排在 TSO 下是否被允许,与弱内存平台有何区别?

A TSO 允许 store-load 重排,但 store-store、load-load 保持顺序;弱内存允许更多重排 ✓ 正确答案
B TSO 允许所有重排
C 弱内存只允许 store-load 重排
D TSO 与弱内存重排集合相同
#

3. 缓存一致性协议(MESI)保证单地址一致,为何仍需要内存顺序约束来保证多地址可观察顺序?

A 缓存一致性已解决多地址顺序
B MESI 保证多地址顺序
C MESI 保证单地址一致,但多地址可观察顺序需内存顺序约束(屏障)保证 ✓ 正确答案
D 内存顺序约束无关缓存
#

4. 流水线的结构冒险、数据冒险、控制冒险分别由什么引起?各自常用的缓解手段是什么?

A 三类冒险都由资源不足引起
B 结构冒险由资源冲突引起(资源重复缓解),数据冒险由数据依赖引起(转发/调度缓解),控制冒险由分支引起(分支预测缓解) ✓ 正确答案
C 数据冒险用分支预测缓解
D 控制冒险用转发缓解
#

5. Tomasulo 算法通过保留站与寄存器重命名消除 WAR/WAW 假依赖,其核心思想是什么?

A Tomasulo 用寄存器重命名把 WAR/WAW 假依赖变成独立指令,保留站跟踪数据就绪,只保留 RAW 真依赖 ✓ 正确答案
B Tomasulo 消除 RAW 依赖
C 重命名不消除 WAR/WAW
D 保留站跟踪寄存器名而非数据
#

6. 寄存器重命名如何把架构寄存器映射到更多物理寄存器,从而释放指令级并行?

A 重命名用映射表把架构寄存器映射到更多物理寄存器,化解 WAR/WAW,只受 RAW 约束,释放 ILP ✓ 正确答案
B 重命名没有更多物理寄存器
C 重命名消除 RAW 依赖
D 31 架构寄存器映射到相同数量物理寄存器
#

7. 分支预测失败时为何要冲刷流水线中已取指/译码的指令?流水线级数越深代价越大如何理解?

A 级数越深冲刷越少
B 预测失败无需冲刷
C 预测失败时冲刷错误路径指令重新取指,流水线级数越深冲刷指令越多、代价越大 ✓ 正确答案
D 冲刷只影响取指无代价
#

8. 乱序执行但顺序提交如何借助重排序缓冲(ROB)保证精确异常?

A ROB 支持乱序提交
B ROB 按程序顺序提交,乱序执行下异常时丢弃未提交指令、保留已提交状态,实现精确异常 ✓ 正确答案
C 精确异常无需 ROB
D 异常时已提交指令也回滚
#

9. load/store 队列在乱序执行中如何维护内存访问顺序并实现 store-to-load 转发?

A 转发无需别名检测
B load 永远等待 store 提交
C load/store 队列维护内存顺序并做别名检测,store-to-load 转发让 load 直接从未提交 store 取数据降低延迟 ✓ 正确答案
D load/store 队列不维护顺序
#

10. 静态分支预测(如向后跳转预测为 taken)与动态预测(两级历史、TAGE)的适用场景有何差异?

A 动态预测零开销
B 静态预测精度高于动态
C TAGE 是静态预测器
D 静态预测简单低精度零历史开销,动态预测(两级/TAGE)高精度有历史表开销,高性能处理器用动态 ✓ 正确答案
#

11. 为什么现代超标量处理器追求更宽的发射宽度,却又受限于取指带宽与分支预测精度?

A 分支预测精度不影响宽发射
B 发射宽度可无限增大无限制
C 宽发射提升 ILP,但受取指带宽与分支预测精度限制,取指不足或预测不准使性能受限 ✓ 正确答案
D 取指带宽与发射无关
#

12. C++ memory_order_seq_cst 在 x86 与 ARM 上的实现差异,为什么 x86 上 seq_cst store 常需 xchg 或 mfence 而 ARM 需要显式屏障,开销来自哪里?

A x86 上 seq_cst store 用 xchg/mfence 阻止 store-load 重排,ARM 用显式屏障,开销来自 full barrier 序列化 ✓ 正确答案
B x86 上 seq_cst store 无需屏障
C ARM 上 seq_cst 无开销
D seq_cst 比 acquire/release 更便宜
#

13. Dekker 式互斥(两个线程各写自己的标志再读对方标志)为什么在 x86 TSO 下仍可能同时进入临界区,需要什么内存序或屏障才能修复?

A store-load 重排不影响 Dekker
B TSO 下 Dekker 总是安全
C TSO 的 store-load 重排使两个线程可能都读到 0 同时进入临界区,需 seq_cst 或屏障阻止该重排 ✓ 正确答案
D relaxed 语义即可修复 Dekker
#

14. x86 的 store-load 重排为何由 store buffer 引起,mfence/lock 前缀如何强制顺序,对无锁队列的 head/tail 更新有何影响?

A store buffer 不引起重排
B store buffer 引起 store-load 重排,mfence/lock 强制顺序,无锁队列 head/tail 需 release/acquire 保证可见性 ✓ 正确答案
C 无锁队列 head/tail 可用 relaxed
D mfence 不强制顺序
#

15. C11/C++11 六种 memory_order 的强弱关系,relaxed/acquire/release/acq_rel/seq_cst 分别约束哪些重排,为什么 seq_cst 通常最贵?

A acq_rel 弱于 acquire
B relaxed 约束最强
C 强弱关系为 relaxed<acquire/release<acq_rel<seq_cst,seq_cst 要求全局一致序开销最大 ✓ 正确答案
D seq_cst 与 relaxed 等价
#

16. C++ memory_order_consume 为何理论上比 acquire 更便宜却实际常被降级为 acquire,依赖链与编译器保守处理的关系是什么?

A consume 只排序依赖链、理论更便宜,但编译器难以精确实现,常被降级为 acquire ✓ 正确答案
B consume 比 acquire 更严格
C consume 总是比 acquire 便宜且被实现
D consume 无需依赖链
#

17. RCU 读侧为何只需编译屏障或轻量读屏障,写侧发布新版本时如何用 store-release 保证读者看到完整初始化?

A RCU 读侧需 full barrier
B RCU 读侧只读,只需编译屏障;写侧 store-release 保证初始化先于指针发布,读者 acquire 看到完整初始化 ✓ 正确答案
C store-release 使初始化可缺省
D 读者无需 acquire
#

18. 什么是撕裂读写(torn read/write),为什么未对齐或跨缓存行的 64 位访问可能撕裂,C++ 原子类型的对齐保证如何避免?

A 撕裂只影响 32 位
B 对齐与撕裂无关
C 原子类型必然撕裂
D 未对齐或跨缓存行的 64 位访问可能被拆成多次操作而撕裂,C++ 原子类型保证对齐并用原子指令避免 ✓ 正确答案
#

19. IRIW(独立读独立写)场景为什么能区分 TSO 与弱内存模型,两个读者观察到不同写入顺序意味着模型允许哪种重排?

A TSO 允许 IRIW 不一致
B IRIW 中两个读者观察到不同写入顺序说明模型允许写者传播乱序,弱内存允许而 TSO 一般保证一致 ✓ 正确答案
C IRIW 与模型无关
D 弱内存保证 IRIW 一致
#

20. FENCE 指令的 predecessor/successor 读写集合(IORW)如何精确表达所需的排序粒度?

A FENCE 的 pred/succ IORW 参数精确指定排序哪些操作类型,如 W,W 只排序写-写,实现按需屏障 ✓ 正确答案
B FENCE 总是全屏障
C IORW 与排序无关
D FENCE 无法指定操作类型
#

21. 数据依赖中的 RAW、WAR、WAW,哪些是真依赖、哪些只是名字相关(假依赖)?

A 所有依赖都是真依赖
B RAW 是假依赖
C WAR 传递真实数据
D RAW 是真依赖(传递数据),WAR/WAW 是假依赖(名字相关),可被寄存器重命名消除 ✓ 正确答案
#

22. 转发(forwarding/bypassing)如何在不插气泡的情况下解决相邻指令的 RAW 冒险?哪种情况仍必须停顿?

A 转发直接旁路结果解决 ALU 类 RAW,但 load-use 需多周期无法转发,必须停顿 ✓ 正确答案
B 转发解决所有 RAW,无需停顿
C load-use 也可转发
D 转发需插气泡
#

23. x86 的 lock cmpxchg 与 ARM/RISC-V 的 LL/SC 在实现原子读改写上的差异,LL/SC 的虚假失败(spurious failure)如何影响无锁算法设计?

A LL/SC 无法构建原子操作
B LL/SC 无虚假失败
C x86 CAS 有虚假失败
D x86 lock cmpxchg 原子无虚假失败,LL/SC 有虚假失败需重试,无锁算法需容忍重试保证进展 ✓ 正确答案
#

24. 无锁 SPSC 环形队列为何生产者只需 release 写、消费者只需 acquire 读,误用 relaxed 会破坏什么可见性保证?

A 生产者 release 写 head、消费者 acquire 读 head,保证数据可见;relaxed 会破坏数据就绪可见性 ✓ 正确答案
B SPSC 可用 relaxed
C release 不保证数据可见
D acquire 读 head 后数据可能未发布
#

25. 双重检查锁定(DCLP)为何需要 acquire/release 或原子指针,缺失时读者如何可能观察到部分构造的对象?

A 读者总是看到完整对象
B DCLP 无需内存序
C volatile 足以保证 DCLP 正确
D DCLP 需 release 发布指针、acquire 读指针,缺失时重排可能使读者看到部分构造对象 ✓ 正确答案
#

26. load-load、load-store、store-load、store-store 四类屏障分别禁止哪些重排,lfence/sfence/mfence 与 C++ acquire/release 如何对应?

A acquire 对应 store 前屏障
B lfence 是 store 屏障
C mfence 只禁止 load 重排
D lfence 是 load 屏障、sfence 是 store 屏障、mfence 是全屏障,acquire 对应 load 后屏障、release 对应 store 前屏障 ✓ 正确答案
#

27. memory_order_relaxed 的合法用途边界,为何无符号计数器的单调累加可用 relaxed,而发布指针或控制依赖必须升级内存序?

A relaxed 保证顺序
B relaxed 可发布指针
C 无符号计数器单调累加可用 relaxed(仅需原子性),但发布指针或控制依赖需升级到 release/acquire ✓ 正确答案
D 计数累加也需 release
#

28. 原子 RMW(如 xchg/cmpxchg)为何需要缓存行独占,多线程争用同一原子变量时 cache line ping-pong 如何放大延迟?

A RMW 无需独占缓存行
B RMW 需缓存行独占,多线程争用导致缓存行 ping-pong(失效重取),放大延迟 ✓ 正确答案
C ping-pong 不放大延迟
D 争用原子变量无性能影响
#

29. C/C++ 中并发读写非原子变量为何是未定义行为而非只读到旧值,编译器可能基于单线程假设做什么破坏性优化?

A 数据竞争只读到旧值,安全
B 并发读写非原子变量是 UB,编译器基于单线程假设做缓存/重排/合并等破坏性优化 ✓ 正确答案
C 编译器假设多线程
D 非原子变量并发安全
#

30. 线程间 happens-before 关系如何由 mutex 解锁/加锁、atomic release/acquire、thread join 建立,为什么仅靠时间先后不构成同步?

A 时间先后即可保证可见性
B mutex 解锁/加锁、release/acquire、join 建立 happens-before 提供可见性保证,仅时间先后不构成同步 ✓ 正确答案
C 无同步的先后写也可见
D mutex 不建立 happens-before
#

31. 为什么 x86 采用 TSO 而 ARM/RISC-V 采用弱内存模型,写缓冲与推测执行等硬件机制如何塑造两种模型的允许重排集合?

A ARM 采用 TSO
B x86 因历史采用 TSO(主要允许 store-load 重排),ARM/RISC-V 为性能用弱内存,写缓冲与推测塑造允许重排集合 ✓ 正确答案
C 写缓冲与重排无关
D TSO 允许所有重排
#

32. ARMv8 的 DMB/DSB 与 C++ acquire/release 的映射关系,编译器何时插入屏障,DSB 相对 DMB 额外保证什么?

A DMB 与 DSB 完全等价
B acquire/release 映射为 DMB,编译器在原子操作处插入屏障;DSB 额外等待所有访问完成并同步执行 ✓ 正确答案
C acquire 映射为 DSB
D 编译器永不插入屏障
#

33. RISC-V 原子指令的 .aq/.rl 后缀与 fence 指令的关系,什么场景只需带后缀的 AMO,什么场景仍需显式 fence?

A fence 永远可以替代 acquire
B .aq/.rl 是完整全屏障
C 带后缀的 AMO 无需任何排序
D .aq/.rl 提供 acquire/release 单侧语义,适合原子同步;需全序/seq_cst 或排序非原子时仍需显式 fence ✓ 正确答案
#

34. 原子操作与 volatile 的区别,为什么 volatile 不能替代 atomic,编译器与硬件分别可能做哪些优化?

A volatile 只阻止编译器优化,不提供原子性与内存顺序,不能替代 atomic ✓ 正确答案
B volatile 提供原子读改写
C volatile 阻止 CPU 重排
D atomic 与 volatile 等价
#

35. 无锁栈(Treiber stack)的 ABA 问题,为什么 CAS 循环中可能读到看似相同的旧指针,tagged pointer 如何解决?

A tagged pointer 不解决 ABA
B ABA 不影响 CAS
C ABA 是 CAS 只比较值、弹出再推入后值相同但语义已变,tagged pointer 用 tag 版本号检测复用避免 ABA ✓ 正确答案
D CAS 比较 tag 与指针无关
#

36. x86-TSO 与 ARMv8/RISC-V 弱内存模型在允许的重排范围上有何差异,编程上意味着什么?

A x86 允许所有重排
B 弱内存允许更多重排(store-store/load-load/load-store/store-load),x86 TSO 主要允许 store-load,可移植代码需显式内存序 ✓ 正确答案
C 弱内存比 x86 顺序更严格
D 移植 x86 代码到 ARM 无风险
#

37. RISC-V 的 AMO 指令(amoswap/amoadd 等)与 LR/SC 序列在实现原子操作上的适用场景差异?

A LR/SC 也是单条指令
B AMO 是单条原子指令实现预定义操作(高效无失败),LR/SC 用于 CAS 或自定义原子操作(通用但有虚假失败) ✓ 正确答案
C AMO 可做任意原子操作
D AMO 有虚假失败
#

38. RISC-V 弱内存模型 RVWMO 与 ARMv8 的内存模型在排序规则设计上有哪些共通与不同?

A 两者都是弱内存、支持 acquire/release、强调显式同步,差异在具体重排规则与屏障/原子指令形式 ✓ 正确答案
B RVWMO 是强内存
C ARMv8 无需显式同步
D 两者规则完全相同
#

39. 自旋锁实现为何必须用 acquire 获取、release 释放,遗漏内存序时临界区内的共享读写在多核上会出现什么问题?

A 自旋锁须 acquire 获取、release 释放,保证临界区读写被锁保护并可见,遗漏内存序会使临界区读写逃出锁导致数据竞争 ✓ 正确答案
B 自旋锁可用 relaxed
C 内存序与自旋锁无关
D 遗漏内存序只在单核有问题
#

40. volatile 在嵌入式多核场景的局限,为什么它只阻止编译器优化而不约束 CPU 乱序,与 atomic 的根本差异在哪里?

A volatile 提供原子读改写
B volatile 约束 CPU 乱序
C volatile 只阻止编译器优化,不约束 CPU 乱序、不提供原子性,多核并发需 atomic(提供原子+顺序+可见性) ✓ 正确答案
D volatile 与 atomic 等价
#

41. 缓存一致性协议已保证单地址一致,为何仍需要屏障指令来约束多地址的观察顺序,两者解决问题的层次有何不同?

A 屏障解决单地址一致
B 一致性已保证多地址顺序
C 缓存一致性保证单地址值一致,屏障约束多地址观察顺序,两者层次不同 ✓ 正确答案
D 一致性协议已解决顺序问题
#

42. 编译期重排与运行期重排的区别,为什么正确代码需要同时防止编译器(如 GCC 的 memory clobber)与 CPU(fence)两层的重排?

A 只需防一层即可
B memory clobber 防 CPU 重排
C fence 防编译器重排
D 编译期重排由编译器、运行期重排由 CPU 完成,memory clobber 防编译器、fence 防 CPU,需同时防护 ✓ 正确答案
#

43. seqlock 读者为何需要 acquire 语义或显式屏障,检测到序号变化后重试即可,这与锁保护相比省去了什么?

A 读者需 acquire 保证读序一致,序号检测替代锁,无写者时读者不加锁、可并行,省去锁获取与读者互斥 ✓ 正确答案
B 读者无需屏障
C 读者也需加锁
D 序号检测与顺序无关
#

44. 编译器屏障(GCC 的 asm volatile 空汇编加 memory clobber)与硬件 fence 的区别,什么场景下只需要编译器屏障即可?

A 多核乱序也只需编译器屏障
B 编译器屏障防 CPU 重排
C 硬件 fence 无指令
D 编译器屏障(asm volatile memory clobber)只防编译器重排、无指令,硬件 fence 防 CPU 重排;单核或硬件已提供顺序时只需编译器屏障 ✓ 正确答案