--- tags: [test/review, java, lock-escalation, CAS, AQS, optimistic-lock] create time: 2026-08-09 12:00 --- # 锁升级与 CAS 机制_测试题 ## 概述 本测试覆盖 synchronized 锁升级机制(偏向→轻量级→重量级)、CAS 原子操作原理、ABA 问题及其解决方案、AQS 框架设计等核心内容,共 10 道题目(6 道选择题 + 3 道填空题 + 1 道简答题)。 --- ## 一、选择题(6道,由浅入深) > **难度阶梯**: Q1-Q2 基础概念 → Q3-Q4 核心原理 → Q5-Q6 深入应用/边界场景 ### Q1(基础)— 考察定义层面 synchronized 锁升级的正确顺序是: A. 重量级 → 轻量级 → 偏向锁 B. 偏向锁 → 轻量级 → 重量级 C. 轻量级 → 偏向锁 → 重量级 D. 偏向锁 → 重量级 → 轻量级 ### Q2(基础)— 考察概念记忆 关于偏向锁,以下说法**正确**的是: A. JDK 17 中仍然默认启用,通过 `-XX:+UseBiasedLocking` 控制 B. 偏向锁撤销时需要全局 STW,代价较高,因此在真实场景中很少能发挥优势 C. 偏向锁状态下,同一线程重复获取锁也需要进行一次 CAS 操作 D. 当有其他线程尝试获取偏向锁时,当前锁会直接升级为重量级锁 ### Q3(进阶)— 考察核心原理 在轻量级锁获取过程中,线程首先在栈帧中创建 Lock Record,然后使用 CAS 将对象头的 Mark Word 替换为指向 Lock Record 的指针。如果 CAS 失败,接下来会发生什么? A. 立即升级为重量级锁 B. 线程进入睡眠状态等待其他线程释放锁 C. 当前线程自旋重试(最多循环指定次数) D. 抛出 ConcurrencyModificationException 异常 ### Q4(进阶)— 考察比较与辨析 `synchronized` 关键字与 `ReentrantLock` 的主要区别,以下描述**错误**的是: A. synchronized 是 JVM 内置关键字,ReentrantLock 是 JDK API 层的实现 B. synchronized 支持锁升级(偏向→轻量级→重量级),ReentrantLock 没有锁升级机制 C. synchronized 支持超时获取锁(tryLock 语法),ReentrantLock 不支持 D. ReentrantLock 可选公平锁和非公平锁,synchronized 始终是非公平的 ### Q5(深入)— 考察场景推理 在某高并发计数器场景中,开发者使用 `AtomicInteger` 代替 `synchronized` 来提升性能。但在实际压测中发现,随着并发量的增加,CPU 使用率反而急剧升高,QPS 并未如预期增长。最可能的原因是: A. AtomicInteger 本身存在线程安全问题,在高并发下会漏计 B. CAS 长时间自旋增加了 CPU 开销,竞争激烈时应升级为重量级锁或使用其他方案 C. AtomicInteger 的 value 字段缺少 volatile 修饰,线程间看不到最新值 D. AtomicInteger 的 incrementAndGet() 不是原子操作 ### Q6(深入)— 考察源码级理解 AQS 的 CLH 队列中,当一个节点的状态为 `SIGNAL` 时,意味着什么? A. 该线程已取消等待(CANCELLED) B. 该线程的后继节点需要被 unpark(即前驱释放锁后会唤醒后继) C. 该线程正在等待条件变量(CONDITION) D. 该节点处于共享模式传播状态(PROPAGATE) --- ## 二、填空题(3道) ### F1 — 填空1 在轻量级锁的获取流程中,竞争发生时线程会进行自旋重试。如果自旋超过阈值(默认 __(1)__ 次,可通过 `-XX:PreBlockSpin` 调整),就会升级为__(2)__锁。此时未获得锁的线程会被__(3)__挂起,进入 OS 的等待队列,需要切换到内核态,这是性能损耗最大的环节。 > **提示**: 回忆轻量级锁的自旋阈值和重量级锁的关键特征。 ### F2 — 填空2 CAS 是 CPU 级别的原语指令,在 x86 架构下对应__(1)__汇编指令。在多核环境下通过总线锁或缓存锁保证原子性。CAS 的一个经典问题是__(2)__问题——线程 T1 读取值为 A,T2 把值改为 B 再改回 A,T1 的 CAS 检查时发现值仍是 A 但实际值已经被修改过。解决思路是给值加__(3)__,每次变更版本号加 1。 > **提示**: x86 的 cmpxchg 指令是 CAS 的硬件基础,ABA 的解法是加版本戳。 ### F3 — 填空3 AQS 的核心是一个 `volatile int state` 变量。在不同同步器中,state 的含义不同:ReentrantLock 中 state 表示__(1)__;CountDownLatch 中 state 表示__(2)__(递减到 0 后触发);Semaphore 中 state 表示__(3)__。 > **提示**: state 的含义取决于具体实现类的语义,回忆文中 AQS 状态机表格。 --- ## 三、简答题(1道) ### S1 某电商秒杀系统在订单扣减环节面临高并发竞争。开发团队最初使用 `synchronized` 保护库存扣减逻辑,后发现性能瓶颈。团队计划迁移到 `ReentrantLock` + AQS 的方案。已知以下条件: - 峰值 QPS 约 5000 - 库存扣减需要保证原子性和一致性 - 部分上游服务依赖超时较短(200ms),需要支持锁的超时获取 请回答: 1. 从 synchronized 迁移到 ReentrantLock 的主要优势有哪些?列出至少 3 个。 2. 如果采用 ReentrantLock 的非公平锁模式,请简述其 tryAcquire 的核心逻辑流程(涉及 CAS 和重入)。 3. 在 AQS 的 CLH 队列中,如果一个节点的线程已经超时,AQS 如何处理这个节点?节点可能的状态有哪些? > **答题框架提示**: > - 第 1 问从公平性、中断、超时、Condition 等维度对比 > - 第 2 问结合 ReentrantLock tryAcquire 的代码逻辑 > - 第 3 问列举 AQS 节点状态及其含义 --- ## 参考答案与解析 ### 选择题答案 | 题号 | 正确答案 | 解析 | |------|---------|------| | Q1 | B | synchronized 的锁升级路径是固定的:无锁→偏向锁→轻量级锁→重量级锁。一旦升级到重量级就不会再降级(除非竞争减弱时从退出队列恢复)。 | | Q2 | B | 偏向锁在实际场景中"永远只有一个人访问"的概率很低,而撤销代价高(需全局 STW),因此 JDK 15 标记废弃、JDK 17 移除。A 错在版本不对,C 错在偏向锁重复获取无需 CAS,D 错在是升级为轻量级而非直接重量级。 | | Q3 | C | CAS 失败后线程会自旋重试,最多循环指定次数(默认 10 次)。超过阈值才升级为重量级锁。不会立即升或抛异常。 | | Q4 | C | C 是错误的描述:synchronized 不支持超时获取锁,ReentrantLock 才有 `tryLock(timeout)`。A、B、D 都是正确的。 | | Q5 | B | 在高并发竞争下,CAS 自旋重试会消耗大量 CPU,这就是为什么有界锁最终会升级为重量级锁。QPS 不上涨是因为 CPU 变成了瓶颈。 | | Q6 | B | SIGNAL 状态表示该节点的后继节点需要被 unpark——即前驱释放锁后会唤醒后继。CANCELLED=已取消,CONDITION=等待条件变量,PROPAGATE=共享模式传播。 | ### 填空题答案 | 题号 | 答案 | 解析 | |------|------|------| | F1 | (1)10 (2)重量级 (3)阻塞 | 轻量级锁自旋阈值为 10 次,超时会退化为重量级锁。重量级锁通过 Monitor 实现,线程阻塞挂起需要内核态切换。 | | F2 | (1)cmpxchg (2)ABA (3)版本号 | cmpxchg 是 x86 的 CAS 汇编指令。ABA 问题的解法是 AtomicStampedReference ——给值加版本号。 | | F3 | (1)持有锁的次数(重入计数) (2)计数器初始值 (3)可用许可证数量 | state 的含义因同步器而异,但其声明始终是 volatile int,保证可见性。 | ### 简答题参考答案 S1:**参考答案要点**: 1. 主要优势:① 支持公平锁/非公平锁可选,可以根据业务选择合适的策略;② 支持 `lockInterruptibly()` 响应中断,避免因某个锁永远拿不到而导致线程无限阻塞;③ 支持 `tryLock(timeout)` 超时获取,满足上游 200ms 超时约束;④ 支持多个 Condition 变量,比 synchronized 的 wait()/notify() 更灵活。 2. 非公平锁 tryAcquire 核心流程:① 先尝试直接用 CAS 拿锁(`compareAndSetState(0, acquires)`),成功则设置独占线程;② 如果 state 不为 0,判断当前线程是否为已有的独占线程,如果是则重入累加 state;③ 都不满足则返回 false,走 AQS 排队流程。 3. AQS 节点可能的状态包括:`CANCELLED`(值为 1,已取消等待)、`SIGNAL`(值为 -1,后继需 unpark)、`CONDITION`(值为 -2,等待条件变量)、`PROPAGATE`(值为 -3,共享模式传播)。如果节点超时,通常会将其状态设为 CANCELLED 并从队列中移除(由前驱节点的 unlinkCancelledNodes 或 self-unpark 机制处理)。 **评分标准**:答出任意 2 个要点即可得满分;完全正确需覆盖全部要点。 ## 关联笔记 - [[01.Java/concurrent/线程池参数与拒绝策略]]