线程、协程与内存模型

共 63 题
#

1. POSIX 线程取消点、清理处理器与线程局部存储析构函数的执行顺序是什么?

A 取消时清理处理器按 FIFO 顺序执行
B 延迟取消在取消点触发,先逆序执行清理处理器,再运行 TLS 析构函数,最后线程终止 ✓ 正确答案
C 异步取消不会破坏线程内部状态
D pthread_exit 不执行清理处理器
#

2. 用户态协程在系统调用阻塞时为什么可能拖住整个调度线程,常见运行时如何规避?

A 阻塞系统调用只影响发起协程
B 协程共享 OS 线程,阻塞系统调用会让整个线程睡眠拖住所有协程;需用非阻塞 I/O+事件循环、io_uring 或阻塞线程池规避 ✓ 正确答案
C 协程切换由内核完成
D 协程内可以安全地直接 sleep 阻塞
#

3. 线程本地存储 TLS 通过 fs/gs 段、__thread 与 pthread_key 三种方式访问时分别有何开销与生命周期?

A __thread 经段基址+编译期偏移直接寻址开销最低、生命周期随线程;pthread_key 需查表访问并支持析构回调,开销高 ✓ 正确答案
B pthread_key 的访问开销低于 __thread
C __thread 变量在线程退出时自动调用析构函数
D fs/gs 段基址由用户程序自行设置
#

4. Go goroutine 的 G-M-P 模型相比原生线程一对一映射,解决了哪些调度瓶颈,又带来哪些抢占语义难题?

A Go 调度完全依赖内核抢占
B G 与 OS 线程一对一
C P 的数量等于 G 的数量
D G-M-P 让轻量 G 在少量 M 上用户态调度(work-stealing),解决线程创建/切换/栈开销;代价是需要信号级异步抢占与 syscall 边界处理 ✓ 正确答案
#

5. 工作窃取调度器如何处理本地队列、全局队列与亲和性,哪些负载会破坏公平性?

A 全局队列是任务的主要入口
B 窃取总是跨 node 优先
C worker 本地队列优先、窃取头部、全局队列兜底,并尽量同 node 窃取保亲和;长任务、任务不均与依赖链会破坏公平性 ✓ 正确答案
D 大任务不会影响其他 worker
#

6. 当一个线程内的协程调用阻塞 pthread mutex 时,协程调度器是否会陷入调度死锁,常见规避手段是什么?

A 阻塞锁只阻塞当前协程
B 协程调用阻塞 pthread mutex 会使整个 OS 线程睡眠,若锁持有人在同线程且未运行则调度死锁;应改用协程级异步锁或外派阻塞线程 ✓ 正确答案
C 协程内可以放心使用 pthread_mutex_lock
D 阻塞锁由调度器自动跳过
#

7. 在多核环境下,协程亲和性如何与工作线程绑定,何时应当让协程迁移到其他工作线程执行?

A 亲和性只影响性能不影响正确性
B 协程永远不应迁移
C 本地队列优先与显式绑定提供协程亲和;本地过载、NUMA 失衡、阻塞外派与硬线程依赖是迁移的合理时机 ✓ 正确答案
D 窃取不改变协程的 worker 归属
#

8. Java 虚拟线程(Virtual Thread)与 Go goroutine 在调度实现、内核线程映射和 pinning 行为上有何关键差异?

A pin 对吞吐无影响
B Java VT 也由 G-M-P 调度
C Go 的 goroutine 也会被 synchronized pin
D Go 用 G-M-P 自研调度且几乎不 pin;Java VT 挂到 ForkJoinPool carrier 上执行,synchronized(JDK 24 前)与 JNI 会 pin 住 carrier ✓ 正确答案
#

9. Linux CFS 的虚拟运行时间如何结合 nice 权重选择下一个任务,唤醒抢占何时发生?

A CFS 按 vruntime(实际运行时间×1024/权重)排序取最小者运行;唤醒任务 vruntime 小于阈值(sched_wakeup_granularity_ns)时触发抢占 ✓ 正确答案
B nice 权重不影响 vruntime 增速
C CFS 总是选择 vruntime 最大的任务
D 唤醒抢占与 vruntime 无关
#

10. SCHED_FIFO、SCHED_RR 与 SCHED_DEADLINE 的准入、抢占和带宽隔离语义有何差异?

A FIFO 无时间片且同优先级不抢占,RR 同优先级轮转,DEADLINE 经 CBS 准入控制并提供每任务带宽预算隔离 ✓ 正确答案
B FIFO 有带宽隔离
C DEADLINE 任务可无限占用 CPU
D RR 与 FIFO 完全相同
#

11. Linux 调度域(sched domain)如何在多核拓扑上分组,跨域负载均衡与触发频率的默认值有何规律?

A 调度域按 SMT/MC/NUMA 拓扑嵌套分组,负载均衡由内向外逐级执行,balance_interval 随域层级增大而增大 ✓ 正确答案
B 所有域共用同一均衡周期
C 跨域均衡频率高于域内
D 调度域只包含物理核不含超线程
#

12. cgroup v1 与 v2 的 CPU shares/quota/period 在带宽控制语义上有何差别,为何 v2 的 burst 参数允许积攒算力?

A shares 是争用时的相对权重,quota/period 是绝对上限;v2 的 burst 允许借支历史未用配额应对突发,长期平均仍受 quota 约束 ✓ 正确答案
B v2 的 burst 取消 quota 限制
C shares 限制绝对 CPU 时间
D v1 与 v2 的 CPU 接口完全相同
#

13. 优先级反转如何形成,优先级继承互斥量为什么不能解决所有锁链问题?

A 反转由低优先级持锁+中优先级抢占形成;继承临时提升持锁者优先级,但锁链传播、非锁资源与窗口延迟使其无法解决所有问题 ✓ 正确答案
B 优先级继承能消除一切延迟问题
C 反转只发生在单核系统
D 继承锁可以防死锁
#

14. CFS 的红黑树节点选择是否会因 nr_running 抖动而退化为线性扫描,min_vruntime 在唤醒抢占中如何防止饥饿?

A CFS 取红黑树最左节点,选择 O(log n) 稳定不随任务数退化;min_vruntime 钳制唤醒/新任务起点,防止欠账回归造成饥饿 ✓ 正确答案
B nr_running 增大时选择退化为线性
C min_vruntime 越大越饥饿
D 唤醒任务可以携带全部历史 vruntime 回归
#

15. nice 值的优先级权重通过 1.25^nice 映射后,两个 nice=-5 的进程与一个 nice=0 的进程在 CPU 时间分配上是否线性?

A nice=-5 与 nice=0 权重相同
B 两个 nice=-5 与一个 nice=0 平均分配
C nice 每级影响相同且线性
D nice 权重按 1.25^nice 乘性映射,两个 nice=-5(各≈3.05 份)与一个 nice=0(1 份)的占比为约 86%:14%,非线性 ✓ 正确答案
#

16. 在 NUMA 服务器上同时观察到迁移增多和远端访存升高,应如何调整负载均衡与 CPU 亲和性?

A 钉核会必然提升吞吐
B 迁移与远端访存无关联
C 自动 NUMA 均衡总是有益的
D 迁移破坏局部性导致远端访存升高并互相强化;应关闭自动 NUMA 均衡、钉核绑定、调整跨域均衡频率并分区部署验证 ✓ 正确答案
#

17. 使用 chrt 调整调度策略后未观察到调度延迟下降,可能被 cgroup、autogroup 或 nice 二次覆盖的原因是什么?

A chrt 之后延迟必然下降
B chrt 只改任务级策略,cgroup 的 quota/rt_runtime、autogroup 组内摊薄与 nice 回写会在更高层覆盖其效果,需逐层排查 ✓ 正确答案
C autogroup 与调度无关
D cgroup 不影响 RT 任务
#

18. 当 SCHED_DEADLINE 任务的运行时间超出 runtime 而准入控制失败,调度器会怎样回退到其他策略?

A 运行超 budget 时 CBS 冻结任务到下一周期重新充能(非策略回退);创建时准入失败则直接拒绝(EBUSY) ✓ 正确答案
B 超预算后任务自动降级为 FIFO
C DEADLINE 任务的运行时间不受限制
D 准入控制与 runtime 无关
#

19. 在大规模线程池(数千线程)上开启 nice=19 仍观察到调度延迟升高,可能与 sched_latency_ns 和 nr_latency 调参有关吗?

A 任务数超阈值后 slice 受 sched_min_granularity 下限约束,数千线程的轮转周期放大导致延迟升高,nice 权重只稀释份额;调参缓解有限,应减少任务数 ✓ 正确答案
B nice=19 保证低延迟
C sched_latency_ns 与任务数无关
D 线程数不影响调度延迟
#

20. 异构 CPU 调度器(如 EAS)如何在大核小核间放置任务,能耗模型是否需要硬件支持的 P-state 表?

A EAS 用任务预测负载与 Energy Model(频率-功耗 OPP 表)估算各候选 CPU 能耗并选最小能耗放置;表缺失时降级为近似模型 ✓ 正确答案
B EAS 总是把任务放大核
C EAS 不需要功耗数据
D 能耗模型与 P-state 无关
#

21. 互斥锁、读写锁、序列锁和 RCU 分别适合怎样的读写比例与临界区?

A rwlock 适合读多写少、seqlock 适合写多读少且容忍重试、RCU 适合读极多写极少且允许延迟回收 ✓ 正确答案
B RCU 的读者需要加锁
C seqlock 写者需要等读者退出
D rwlock 的写者不会饥饿
#

22. futex 的 FUTEX_WAIT/FUTEX_WAKE 在用户态与内核态切换路径上的开销如何测量,contended 锁为何比 spinlock 更节能?

A futex 无争用时仅用户态原子操作,争用时经 WAIT/WAKE 两次系统调用与调度切换;睡眠等待让出 CPU,比 spinlock 忙轮询更节能 ✓ 正确答案
B futex 每次加锁都进内核
C spinlock 等待时线程睡眠
D futex 与 spinlock 功耗相同
#

23. Go goroutine 起始栈 2KB(dynamic stack)vs OS thread 8MB 的内存开销?

A goroutine 栈 2KB 起按需扩容,增长时拷贝旧栈并重写栈上指针;对比线程 8MB 固定栈,支持百万级并发且免栈溢出崩溃 ✓ 正确答案
B goroutine 栈固定 8MB
C 栈拷贝不需要指针信息
D goroutine 栈与 GC 无关
#

24. Virtual Thread 在 Tomcat Jetty Netty 集成时的 executor 替换?

A Tomcat/Jetty 可将请求 executor 换为虚拟线程 executor;Netty 保留事件循环、用 VT 执行阻塞业务;需注意 synchronized pin 与 ThreadLocal 放大 ✓ 正确答案
B Netty 的 event loop 应替换为虚拟线程
C 虚拟线程不适用于阻塞式业务代码
D 虚拟线程数量仍受平台线程数限制
#

25. ticket spinlock 与 MCS lock 在缓存行争用上的差异是什么,多核 NUMA 下为何 MCS 更公平?

A ticket lock 所有等待者自旋同一缓存行,释放时惊群式争抢且远端流量大;MCS 每等待者自旋本地节点、释放单点传递后继者,NUMA 下更公平 ✓ 正确答案
B ticket lock 没有缓存行争用
C MCS lock 获取顺序不保证
D MCS 释放时唤醒全部等待者
#

26. 无锁栈中的 ABA 问题如何出现,版本标签、hazard pointer 与 epoch reclamation 各如何处理?

A tag 可以解决内存回收
B ABA 是值被改回原值导致 CAS 误判,tag 计数器解决误判;hazard pointer 与 epoch reclamation 解决对象延迟回收的 UAF,两者配合 ✓ 正确答案
C ABA 只发生在有锁代码
D hazard pointer 不需要读侧协作
#

27. 读写锁在写饥饿、写优先与读优先三种实现下各自的偏向行为,如何用 seqlock 兼顾一致性读与偶发写?

A 读优先可饿死写者、写优先可饿死读者、公平实现按到达顺序;seqlock 写者不等读者,读者靠序号校验重试保一致性 ✓ 正确答案
B seqlock 读者需要加锁
C 写优先实现读者不会饥饿
D seqlock 适合大对象频繁读
#

28. RCU 的宽限窗口(grace period)由什么机制保证,CPU 热插拔和抢占如何影响 read-side 临界区?

A RCU 读者需要加锁保护
B RCU 宽限期由各 CPU/任务报告 quiescent state 完成判定;抢占式 RCU 把读者状态挂到任务上,热插拔需迁移离线 CPU 的回调与状态 ✓ 正确答案
C 热插拔不影响宽限期推进
D 宽限期由读者数量决定
#

29. 排查高并发服务锁争用时,如何从 futex 等待、锁持有时间和缓存行抖动定位根因?

A futex 等待与锁无关
B 用 off-cpu/火焰图定位 futex 等待栈,perf lock 看持锁时间,perf c2c 查伪共享;按缩短临界区、细化粒度、无锁化、缓存行隔离的顺序治理 ✓ 正确答案
C 伪共享只影响单核
D 锁争用只能靠换更快硬件解决
#

30. 无锁队列中生产者与消费者 size 不匹配导致单边堆积时,如何用环形缓冲区的 watermark 触发背压?

A watermark 只能丢弃数据
B 单边堆积导致积压与延迟放大;高水位触发生产者限速/通知/降级、低水位恢复,并用滞回区间防抖,实现环形缓冲背压 ✓ 正确答案
C 背压与水位无关
D 环形缓冲满时生产必然自旋阻塞
#

31. 当条件变量 pthread_cond_wait 被 spurious wakeup 后未重新检查谓词,是否会出现永久错失信号,如何防御?

A wait 返回后谓词必然满足
B 虚假唤醒在 Linux 上不存在
C 虚假唤醒若用 if 检查会跳过未满足的谓词,配合 wait/signal 竞态可永久错失信号;须用 while 重查且谓词在锁内修改检查 ✓ 正确答案
D 谓词可以在锁外修改
#

32. 在不可重入场景下,自旋锁与互斥锁在低/中/高争用区间的吞吐曲线大致是什么形状,背后的功耗代价如何权衡?

A 自旋锁等待时 CPU 进入低功耗
B 高争用下自旋锁吞吐高于互斥锁
C 低争用时两者接近、自旋略快;高争用时自旋忙等空转吞吐骤降且功耗高,互斥锁睡眠让核功耗低;自适应先自旋后睡眠折中 ✓ 正确答案
D 互斥锁在低争用时显著慢于自旋
#

33. acquire/release 原子操作如何发布普通写入,为什么 relaxed 计数不能承担对象发布?

A release store 使其前写入对配对的 acquire load 可见,构成对象发布;relaxed 只保证原子性无排序,无法承担发布与安全回收 ✓ 正确答案
B relaxed 计数足以发布对象
C acquire 只影响本变量读取
D release 保证写入不重排到发布点之后
#

34. Rust 的 Send/Sync 标记如何与原子操作的内存序配合,让编译器在静态期就阻止数据竞争?

A Send/Sync 会自动选择内存序
B Send 允许跨线程转移所有权、Sync 允许 &T 共享,编译器静态拒绝不满足约束的跨线程使用;内存序仍由开发者用 Ordering 正确选择 ✓ 正确答案
C Rc 是 Sync 类型
D 原子操作不需要内存序选择
#

35. volatile 关键字在 C/Java 中的语义为何与 atomic 不同,编译器优化下 volatile 读能保证看到最新值吗?

A Java volatile 保证 i++ 原子
B C volatile 与 Java volatile 语义相同
C C volatile 只是禁优化标记,无原子性无同步;Java volatile 建立 happens-before 保证可见性,但复合操作仍非原子 ✓ 正确答案
D C volatile 保证线程可见性
#

36. out-of-thin-air value 在 Java/C++ 内存模型中为何被禁止,反编译后看到的"凭空值"通常来自何处?

A OOTA 是合法的执行结果
B OOTA 在真实硬件上常见
C 数据竞争产生的旧值属于 OOTA
D OOTA 是读观察到无写来源的值且依赖循环因果,JMM/C++ 模型用因果提交序禁止;实际奇怪值多来自未初始化变量与数据竞争 ✓ 正确答案
#

37. 双重检查锁在缺少正确发布时会看到怎样的部分构造对象,如何用原子指针修复?

A 构造完成后指针赋值不可能被重排
B DCL 只要双重判空就安全
C C 语言的 volatile 可以修复 DCL
D DCL 缺少发布同步时,指针赋值可能先于字段初始化,使锁外读者看到部分构造对象;须用 Java volatile 或 C++ atomic acquire/release 建立 happens-before ✓ 正确答案
#

38. 在 SC、TSO、PSO、RMO 几种内存模型下,同一段无锁代码的可观察结果可能截然不同,原因是什么?

A RMO 比 SC 更严格
B x86 是 SC 模型
C 所有模型允许的重排相同
D 模型允许的重排范围决定合法结果集:TSO 允许 store-load 重排、PSO 加 store-store、RMO 几乎任意重排,故同一无锁代码在不同模型下行为可能不同 ✓ 正确答案
#

39. 当使用 release store + acquire load 传递一个指针时,编译器/CPU 可能破坏对象内部字段的可见性吗?

A release 只保证指针变量本身可见
B 只要字段写发生在 release 前、字段读发生在 acquire 后,配对序保证字段完整可见;破坏可见性源于写序颠倒或错用内存序 ✓ 正确答案
C acquire 不能用于对象发布
D 编译器可以把字段写重排到 release 之后
#

40. consume 内存序在 C++ 中目前为何被建议避免使用,依赖该序的代码在 ARM 上通常靠什么隐式约束保证?

A 编译器总能精确识别依赖链
B consume 比 acquire 更强
C consume 依赖编译器可靠识别依赖链,优化中难以保证故 C++17 建议规避;ARM 因地址依赖保序而几乎免费正确,但可移植性差 ✓ 正确答案
D ARM 上 consume 需要额外 dmb
#

41. 在 Go 的 race detector 视角下,普通 map 并发读写为何被判为 data race,与 sync.Map 的内部 hash 锁机制有何关系?

A 普通 map 并发读写无同步被判 data race 且可能崩溃;sync.Map 用 read 无锁原子读+写路径加锁与 dirty 提升,减少锁使用 ✓ 正确答案
B sync.Map 对每次读写都加锁
C race detector 只检测死锁
D 普通 map 是并发安全的
#

42. 对称协程与非对称协程在 yield/resume 链上的差别,如何用 scheduler-coroutine 模式组织生产-消费?

A 调度器模式不需要背压
B 对称协程只能 yield 给调用者
C 非对称协程可以直接跳转到平级协程
D 非对称协程只能 yield 回 resume 者(层级式),对称协程可把控制直接转移给任意协程;生产-消费常用共享队列+调度器分发实现 ✓ 正确答案
#

43. Java 的 StampedLock 与 ReadWriteLock 在乐观读、升级和中断行为上的差别分别带来哪些隐性 bug?

A StampedLock 支持重入与条件变量
B StampedLock 乐观读需快照+validate 重试、convert 升级失败需回退,且不可重入不支持条件变量;ReadWriteLock 读锁直接升级写锁会死锁 ✓ 正确答案
C 乐观读区可以安全写共享状态
D ReadWriteLock 支持乐观读
#

44. 协程切换时寄存器上下文如何保存,longjmp/setjmp 与显式协程框架的栈切换在 ABI 兼容性上的差异?

A longjmp 会执行中间帧析构
B setjmp 可以跨线程跳转
C setjmp/longjmp 只按调用约定保存跳转所需寄存器且限于单栈非局部跳转;显式协程框架保存完整 ABI 现场并切换独立栈 ✓ 正确答案
D setjmp 保存全部浮点寄存器
#

45. Go 1.22+ 进一步细化 preempt 在 syscall return 的抢占点?

A 抢占只发生在 GC 时
B syscall 返回后 G 直接继续运行无需取 P
C Go 1.22+ 在 syscall 返回路径细化抢占与 P 获取处理,使抢占点更接近返回瞬间,降低高频 syscall 下的调度延迟与抖动 ✓ 正确答案
D 1.22 的修改影响用户代码语义
#

46. Tokio work-stealing 与 Go scheduler 在公平性 / latency 边界的工程取舍?

A Tokio 无抢占,长任务靠用户 await/yield 让出,开销低延迟可控;Go 有异步抢占兜底公平,慢任务不会饿死其他 G,但引入运行时开销 ✓ 正确答案
B Tokio 与 Go 的抢占机制相同
C Go 的长任务会永久占住 P
D Tokio 会在任务中间自动让出
#

47. Go runtime async preemption 引入 SIGURG + signal handler 实现协作 + 抢占式调度?

A 协作式抢占能打断无检查点循环
B 异步抢占可在任意指令打断 G
C Go 1.14+ 用 SIGURG 信号打断长运行 G,handler 在安全点注入抢占(保留协作式安全点约束),使长循环可被让出、GC 停顿可控 ✓ 正确答案
D SIGURG 与抢占无关
#

48. Go 的 G-M-P 模型(Goroutine-Machine-Processor)与 work-stealing 的工程价值?

A G 切换与线程切换成本相同
B M 数量等于 G 数量
C 窃取只发生在本地队列满时
D G-M-P 以约等于核数的 M 承载百万 G,P 持本地队列,空闲 P 窃取实现均衡;syscall 时 P 让渡、GC 以 P 为并行单元 ✓ 正确答案
#

49. Go scheduler 的 sysmon 协程触发 retake 与 preempt 在 10ms GC 抢占的工程价值?

A GC 停顿时间由用户代码决定
B sysmon 是普通 goroutine
C sysmon 周期性监督:超时未让出的 G 触发抢占、阻塞 syscall 超时回收 P、并驱动 netpoll;使 GC STW 与调度延迟有界 ✓ 正确答案
D sysmon 不处理 syscall
#

50. JEP 444(JDK 21)Virtual Thread 基于 java.lang.Thread 与 CarrierThread 的 fork/join 模型?

A 虚拟线程是 OS 线程的别名
B 虚拟线程是 java.lang.Thread 实例,其 Continuation 挂载到 ForkJoinPool 的 carrier 线程执行,阻塞时卸载,经 FJ 队列 fork/join 恢复 ✓ 正确答案
C 虚拟线程不能使用 Thread API
D VT 阻塞时 carrier 也被阻塞
#

51. Virtual Thread 与 Platform Thread 在 pinning(OS 同步调用阻塞 carrier)的工程价值?

A 所有阻塞都能被 VT 卸载
B pin 不影响吞吐
C 平台线程也有 pin 概念
D VT 在不可卸载的阻塞(synchronized、JNI)上会 pin 住 carrier,使并发退化为线程数限制;JEP 491 修复 synchronized、其余用锁替换与监控规避 ✓ 正确答案
#

52. Virtual Thread 在 synchronized 块在 JDK 24+ 不再 pin carrier 的 JEP 491 工程价值?

A JEP 491 不影响 pin
B JEP 491 删除 synchronized 关键字
C synchronized 在 JDK 24 仍需改 ReentrantLock
D JEP 491 让 monitor 状态可随 VT 卸载重挂载,synchronized 阻塞不再 pin carrier,传统同步代码零改造获得虚拟线程扩展性 ✓ 正确答案
#

53. loom 的 Continuation 与 ForkJoinPool 的协同在 structured concurrency?

A Continuation 是 OS 线程
B 结构化并发不需要任务管理
C Continuation 提供 VT 可挂起栈、ForkJoinPool 提供 carrier 执行与窃取;StructuredTaskScope 以作用域托管子任务生命周期与取消传播 ✓ 正确答案
D 子任务可以泄漏出 scope
#

54. 比较有栈协程与无栈协程的栈增长、挂起状态表示和跨语言 ABI 限制?

A 有栈协程以独立栈+寄存器保存现场,可嵌套挂起且兼容任意 C/C++ 调用;无栈协程以编译期帧对象为状态,挂起仅限被改写为协程的调用链 ✓ 正确答案
B 无栈协程可以跨普通 C 函数挂起
C 有栈协程的挂起点只能在函数入口
D 两种协程的挂起机制相同
#

55. 协程框架中常见的栈拷贝优化与 mmap 协程栈如何决定默认栈大小,避免栈溢出时的扩容策略是什么?

A guard page 用于加速访问
B 固定栈永不溢出
C 拷贝栈不需要指针重定位
D mmap 协程栈预留大虚拟区间按页提交,默认栈大小是已提交页概念;扩容有分段栈与拷贝栈(Go 现用,拷贝+指针重写)两派 ✓ 正确答案
#

56. 条件变量为什么必须配合谓词循环使用,虚假唤醒与丢失唤醒如何区分?

A if 检查足以保证正确性
B 虚假唤醒与丢失唤醒相同
C 条件变量必须配谓词循环:虚假唤醒是多余唤醒(重查可消),丢失唤醒是信号在入队前发出(须靠锁内谓词配对预防) ✓ 正确答案
D 丢失唤醒可以由重查解决
#

57. C/C++ data race 为什么导致未定义行为,happens-before 如何由 sequenced-before 与 synchronizes-with 构成?

A data race 是无 hb 的冲突访问,属 UB(编译器优化假设失效);hb 由单线程 sequenced-before 与跨线程 synchronizes-with(原子 release/acquire、锁配对)取传递闭包构成 ✓ 正确答案
B data race 有确定语义
C hb 只包含同一线程内的顺序
D 互斥锁不建立 synchronizes-with
#

58. Java Memory Model(JMM)中的 happens-before 与 C++ memory_order 在发布/获取语义上是否完全对应,关键差异是什么?

A 两者语义完全等价
B JMM 的 volatile 有同步全序(≈seq_cst),C++ 的 acquire/release 仅配对无全序;且 Java volatile 无 RMW/relaxed,data race 非 UB 而 C++ 是 UB ✓ 正确答案
C Java volatile 对应 C++ relaxed
D C++ data race 有定义语义
#

59. sequentially consistent 全序与处理器真实执行顺序有何关系,SC fence 能保证什么?

A seq_cst 与 relaxed 等价
B 真实硬件天然满足 SC
C SC fence 强制刷新 store buffer
D SC 全序是模型抽象,真实处理器(TSO/弱序)会重排;SC fence 是双向全屏障,保证其前后操作在全局序中不跨越 ✓ 正确答案
#

60. Spring WebFlux vs Spring MVC in Virtual Thread 的工程差异?

A WebFlux 与虚拟线程互斥
B WebFlux 也使用每请求一线程模型
C MVC 在虚拟线程上必须改写为响应式
D MVC+虚拟线程保留命令式阻塞写法且兼容 JDBC 等同步库,靠让出 carrier 提升并发;WebFlux 要求全响应式非阻塞,代码与生态约束大 ✓ 正确答案
#

61. Tokio runtime 在 multi-thread scheduler 下 worker thread 跨队列 work-stealing 的工程价值?

A 窃取只在队列满时发生
B Tokio multi-thread 的空闲 worker 从其他 worker 队列窃取任务,实现负载均衡与全核利用;本地 LIFO 保局部性、窃取牺牲局部性换均衡 ✓ 正确答案
C 本地队列是全局共享的
D work-stealing 会增加常态开销
#

62. Tokio 的 LocalSet 在 !Send future 的 per-thread 执行?

A spawn 默认支持 !Send future
B LocalSet 的任务可以跨线程窃取
C LocalSet 把 !Send future 固定在本线程执行(spawn_local,不参与窃取迁移),适合线程亲和任务;代价是负载均衡失效且阻塞任务无法外派 ✓ 正确答案
D LocalSet 不需要 block_on 驱动
#

63. tokio::spawn 的 Send + 'static 约束与 channel cross-thread 通信?

A spawn 的 Send+'static 保证任务可被窃取迁移且不悬垂;跨线程通信用 channel 传递 Send 消息,任务间解耦不依赖线程归属 ✓ 正确答案
B Send 约束允许任务捕获 Rc
C 'static 要求任务使用借用数据
D channel 消息不需要 Send