AQS 与显式同步器

共 63 题
#

1. AQS 共享模式中的传播机制如何支持 Semaphore 和 CountDownLatch,何时会连续唤醒后继节点

A 共享模式只唤醒一个后继节点,与独占模式完全相同
B 传播机制只在公平模式下生效
C Semaphore 不需要传播机制,因为它通过自旋实现
D 释放共享许可后,成功获取共享资格的线程会通过 setHeadAndPropagate 继续唤醒后继,形成传播链 ✓ 正确答案
#

2. AQS 在 StampedLock 中的角色

A StampedLock 完全独立于 AQS,不借鉴其任何结构
B StampedLock 借鉴 CLH/AQS 队列思想自建节点队列,自行实现状态机与加锁逻辑 ✓ 正确答案
C StampedLock 基于 synchronized 实现
D StampedLock 继承 AbstractQueuedSynchronizer 并复用其 acquire 模板
#

3. AQS 的 CLH 队列锁变种实现

A 它使用双向链表,节点通过 waitStatus=SIGNAL 告知前驱释放后需唤醒自己 ✓ 正确答案
B 它是纯自旋锁,线程从不阻塞
C 它不处理线程取消的情况
D 它按 LIFO 顺序唤醒等待者
#

4. AQS 的 acquire 失败后如何入队、挂起并被唤醒,tryAcquire 和 tryRelease 的重写契约分别是什么

A tryAcquire 返回 true 表示获取成功并已设置 state,返回 false 表示失败且不改状态 ✓ 正确答案
B tryAcquire 由 AQS 提供默认实现,无需重写
C tryAcquire 失败时也可以修改 state 供后续复用
D tryRelease 必须返回 false 才能唤醒后继
#

5. AQS 的 acquire/release 流程与 tryAcquire 重写

A acquire 成功后节点立即从队列删除并由 GC 回收
B release 无需做事,后继节点会自动唤醒
C tryAcquire 是子类实现的具体获取语义,AQS 只负责排队与阻塞 ✓ 正确答案
D tryAcquire 必须持续自旋直到成功
#

6. AQS 的 addWaiter 失败回退到 enq 的意义

A 快速路径在无竞争时直接 CAS 追加,enq 兜底处理队列初始化与并发 CAS 失败 ✓ 正确答案
B 回退到 enq 是为了避免 CAS 造成的原子性损失
C addWaiter 失败说明队列已损坏
D enq 比 addWaiter 更快,失败时用 enq 提升性能
#

7. AQS 的 propagate 与共享模式的传播

A 防止共享模式下唤醒信号丢失,保证传播继续 ✓ 正确答案
B 标记节点已取消
C 加速独占锁的获取
D 表示节点处于条件队列
#

8. AQS 等待节点取消后如何从同步队列中跳过或清理,取消风暴会造成哪些遍历成本

A 取消节点会一直留在队列中直到任务结束
B 取消不会影响队列遍历性能
C 取消时向前遍历跳过 CANCELLED 节点并修正前后指针,取消风暴会带来 O(n) 遍历成本 ✓ 正确答案
D 取消节点会立即从队列删除,无需遍历
#

9. AbstractQueuedLongSynchronizer 与 AQS 的差异

A 使用不同的队列算法
B state 字段用 long 而非 int,适合需要 64 位状态的同步器 ✓ 正确答案
C 支持更多等待模式
D 性能更高
#

10. AbstractQueuedSynchronizer(AQS)的 CLH 队列锁实现原理与 JDK 25 中的演化

A JDK 25 完全重写了 AQS 的队列结构
B AQS 队列是单向链表
C 虚拟线程不会阻塞在 AQS 上
D AQS 用双向链表组织等待节点,JDK 25 中虚拟线程阻塞在 AQS 上时可卸载载体线程 ✓ 正确答案
#

11. AbstractQueuedSynchronizer(AQS)的核心数据结构与状态位

A 共享模式应继续传播
B 该节点释放后需要唤醒后继节点 ✓ 正确答案
C 节点已取消
D 节点在条件队列中
#

12. CAS 在 AQS(AbstractQueuedSynchronizer)中的作用

A 替代所有阻塞操作
B 只用于初始化
C 原子地更新 state、head/tail 与 waitStatus,实现无锁同步 ✓ 正确答案
D 仅用于统计
#

13. CAS 自旋与 ReentrantLock 各有哪些调度和吞吐影响,如何压测比较

A 自旋永远比锁快
B 自旋在低竞争、短临界区时吞吐高但高竞争时 CPU 空耗;锁在竞争高时靠阻塞省 CPU ✓ 正确答案
C ReentrantLock 从不阻塞
D 两者调度行为完全相同
#

14. Condition.signal 为什么要求当前线程持锁,节点从条件队列转移到同步队列经历哪些步骤

A 转移后节点仍在条件队列中
B signal 要求持锁,节点从条件队列 enq 到同步队列后,被唤醒线程重新竞争锁 ✓ 正确答案
C signal 会立即唤醒所有线程
D signal 无需持锁也可正确工作
#

15. CountDownLatch 与 CyclicBarrier 的差异(一次性 vs 可重用)

A CountDownLatch 用于等待线程会合
B 两者都可重复使用
C CountDownLatch 是计数归零放行、一次性;CyclicBarrier 是 N 方到齐放行、可重用 ✓ 正确答案
D CyclicBarrier 是一次性的
#

16. CountDownLatch 在多模块启动等待的应用

A 无需超时处理
B 用 await 会抛异常
C 在 finally 中 countDown 并带超时 await,避免永久阻塞 ✓ 正确答案
D countDown 次数可以多于模块数
#

17. CyclicBarrier 与 Phaser 在多阶段任务中的动态参与者管理差异

A Phaser 支持 register/arriveAndDeregister 动态调整参与者,CyclicBarrier 构造时固定 ✓ 正确答案
B CyclicBarrier 支持动态注册参与者
C 两者都支持动态参与者
D Phaser 不支持多阶段
#

18. JMH 对 synchronized/ReentrantLock 的对比基准

A 共享对象可设为局部变量以便 JIT 优化
B 只需测单线程即可代表全部
C 预热越少越好
D 需用多线程制造真实竞争并充分预热,防止 JIT 锁消除扭曲结果 ✓ 正确答案
#

19. CyclicBarrier 的 barrierAction 与破损处理

A 屏障破损时其他线程收到 BrokenBarrierException,需 reset 恢复 ✓ 正确答案
B barrierAction 在任意线程到达时执行
C barrierAction 抛异常不影响其他线程
D 破损后无需处理自动恢复
#

20. CyclicBarrier 的屏障动作失败后为何会进入 broken 状态,其他等待线程将收到什么信号

A 屏障会自动重试 action
B 与 barrierAction 无关
C 随机行为
D 防止部分线程永久等待,向所有相关线程广播 BrokenBarrierException ✓ 正确答案
#

21. 虚拟线程阻塞在 ReentrantLock 上通常能卸载载体线程,JEP 491 前 synchronized 或外部原生调用何时仍会钉住载体线程

A 在 ReentrantLock 上阻塞
B 在 synchronized 块内执行阻塞操作或调用原生方法 ✓ 正确答案
C 正常的 park
D 任何阻塞都不会
#

22. JDK 25 虚拟线程与 AQS 的协作边界

A 虚拟线程无法使用 AQS 锁
B AQS 为虚拟线程重写了所有算法
C 虚拟线程阻塞时直接占用载体线程
D 虚拟线程 park 在 AQS 上时卸载载体线程,AQS 排队语义不变 ✓ 正确答案
#

23. JEP 491 消除 synchronized 虚拟线程钉住后,JDK 25 中选择 synchronized 与 ReentrantLock 应看哪些需求

A 默认用 synchronized,需要公平/中断/超时/Condition/tryLock 时用 ReentrantLock ✓ 正确答案
B synchronized 永远更快
C JEP 491 后 synchronized 不可用
D ReentrantLock 不提供公平锁
#

24. Java 9 ReentrantLock 的响应线程优先级调整

A 锁获取顺序由 AQS 队列决定,不依赖线程优先级 ✓ 正确答案
B 优先级在 Java 中可靠生效
C 高优先级线程一定先拿到锁
D Java 9 让优先级决定锁顺序
#

25. Phaser 与 CyclicBarrier 的差异

A Phaser 支持动态注册与多阶段推进,CyclicBarrier 参与方固定且按代推进 ✓ 正确答案
B 两者参与者都固定
C Phaser 不支持多阶段
D CyclicBarrier 支持动态注册
#

26. Phaser 支持动态注册和分阶段推进,与 CyclicBarrier 相比在任务数量变化时应如何选择

A 两者都合适
B Phaser,支持动态 register/arriveAndDeregister ✓ 正确答案
C CountDownLatch
D CyclicBarrier,因为其固定参与方保证稳定
#

27. ReentrantLock 公平锁与非公平锁在吞吐与延迟上的取舍

A 两者行为完全相同
B 非公平锁严格 FIFO
C 公平锁吞吐更高
D 非公平锁可插队、吞吐更高但可能饥饿;公平锁 FIFO、延迟稳定但吞吐略低 ✓ 正确答案
#

28. ReentrantLock 基于 AQS 的公平/非公平实现差异

A 只在 tryAcquire 钩子上不同:公平锁加 hasQueuedPredecessors 检查 ✓ 正确答案
B 差异在 release 上
C 使用了不同的队列结构
D 公平锁不基于 AQS
#

29. ReentrantLock 的公平与非公平实现都基于 AQS 时,吞吐量、锁饥饿和队列竞争为何会不同

A 非公平锁减少唤醒次数(插队者无需等队首唤醒),吞吐更高但可能饥饿 ✓ 正确答案
B 公平锁用了不同队列
C 非公平锁队列竞争更少
D 公平锁从不竞争
#

30. ReentrantLock.tryLock 的应用模式

A tryLock 成功应在 finally 中 unlock,失败时降级处理 ✓ 正确答案
B tryLock 会阻塞等待
C tryLock 不返回布尔值
D 获取成功后无需释放
#

31. ReentrantReadWriteLock 的读锁、写锁状态共用

A 读锁不计数
B 高 16 位存读锁计数、低 16 位存写锁计数 ✓ 正确答案
C 用两个 int 分别存读写
D 用 long 存读锁
#

32. ReentrantReadWriteLock 的读锁升级/降级问题

A 升级性能差
B 升级需要额外状态
C 升级是不可重入的
D 多个读锁同时升级会互相等待导致死锁 ✓ 正确答案
#

33. Semaphore 与 CountDownLatch 在资源池与一次性协调上的工程取舍

A 两者都可重复使用
B Semaphore 许可可回收、适合资源池;CountDownLatch 一次性归零、适合事件等待 ✓ 正确答案
C CountDownLatch 适合限流
D Semaphore 只能使用一次
#

34. Semaphore 与 CountDownLatch 都使用共享同步思想时,前者可重复获取许可证而后者一次性归零,这对资源控制有何影响

A Semaphore 许可可回收、CountDownLatch 一次性归零不可逆 ✓ 正确答案
B 两者都支持资源回收
C 两者都不可重复
D Semaphore 许可单向递减、CountDownLatch 可回收
#

35. Semaphore 在连接池限流的应用

A 在 finally 中 release 归还许可,用 tryAcquire 带超时 ✓ 正确答案
B 获取许可后无需释放
C 用 acquire 无超时最安全
D 许可会永久累计
#

36. Semaphore 的 drainPermits、reducePermits 与动态扩缩容怎样配合,如何防止许可证被永久泄漏

A 用 drainPermits 代替 release
B 许可不会泄漏
C 在 finally 中 release,并监控 availablePermits 发现异常 ✓ 正确答案
D 只 acquire 不 release
#

37. Semaphore 的 tryAcquire/acquireUninterruptibly 的差异

A 两者都非阻塞
B acquireUninterruptibly 会抛中断异常
C tryAcquire 可带超时/非阻塞,acquireUninterruptibly 无限等待且忽略中断 ✓ 正确答案
D 两者都阻塞
#

38. Semaphore 的许可证(Permit)机制与公平模式

A 两种模式都严格 FIFO
B 非公平模式可抢占许可、吞吐更高但可能饥饿;公平模式 FIFO 排队 ✓ 正确答案
C Semaphore 不基于 AQS
D 公平模式允许插队
#

39. Semaphore、CountDownLatch、CyclicBarrier 的适用边界

A 三者可互换
B 资源池限流用 Semaphore,一次性完成等待用 CountDownLatch,多线程会合用 CyclicBarrier ✓ 正确答案
C 限流用 CountDownLatch
D 会合用 CountDownLatch
#

40. StampedLock 常被与 AQS 一起比较,但它并不继承 AQS;请说明其乐观读验证和不可重入特性带来的取舍

A 乐观读无需验证
B StampedLock 可重入
C 乐观读需 validate 验证,不可重入限制了递归加锁 ✓ 正确答案
D StampedLock 无性能优势
#

41. StampedLock 的乐观读不是可重入锁,校验失败、线程中断和锁转换应如何正确处理

A 忽略校验结果
B 继续用旧 stamp 解锁
C 重试或升级为悲观 readLock/转换写锁 ✓ 正确答案
D 直接抛异常
#

42. Thread.join() 与 CountDownLatch 在父子线程协调上的语义差异

A 两者都等待线程终止
B join 等待线程终止,CountDownLatch 等待计数归零事件 ✓ 正确答案
C CountDownLatch 等待线程死亡
D join 等待计数归零
#

43. synchronized 与 ReentrantLock 的功能对比(公平/中断/Condition)

A ReentrantLock 不支持中断
B synchronized 支持公平锁
C ReentrantLock 支持可中断获取、超时 tryLock 与多 Condition ✓ 正确答案
D synchronized 支持多个条件队列
#

44. CountDownLatch、CyclicBarrier、Semaphore 的底层实现如何复用 AQS 状态机?

A Semaphore 用 state 表示许可数,CountDownLatch 用 state 表示剩余计数,都是共享模式 ✓ 正确答案
B 三者都独占模式
C 三者不基于 AQS
D CyclicBarrier 直接继承 AQS
#

45. 如何正确处理 AQS 获取操作的超时和中断,避免取消节点残留、丢失唤醒或业务线程无限等待

A 忽略中断
B 无限等待最安全
C 取消节点、清理链表、恢复中断标志并防止丢失唤醒 ✓ 正确答案
D 只取消不清理
#

46. 如何用 jcstress 与故障注入验证自定义 AQS 同步器的互斥、可见性、超时和中断语义

A 普通单元测试
B 单线程 debug
C 线程 dump
D jcstress 并发压力测试框架 ✓ 正确答案
#

47. 实现一次性门闩式 AQS 同步器时,序列化、取消和重复 release 的行为应如何定义

A 只唤醒一个线程
B 幂等地保持已打开状态,不破坏语义 ✓ 正确答案
C 抛异常
D 重新关闭门闩
#

48. 排查 AQS 锁竞争时,应结合队列长度、持锁时间、阻塞线程栈和 JFR 事件建立哪些诊断证据

A 队列长度、持锁时间、阻塞线程栈、JFR 事件综合判断 ✓ 正确答案
B 只看代码评审
C 只看线程数
D 只看 CPU 使用率
#

49. 自定义 AQS 同步器的关键重写点

A 获取失败需排队
B 需要自旋
C 已取消
D 获取成功且仍有剩余许可可传播 ✓ 正确答案
#

50. 虚拟线程在 AQS 锁上排队时如何卸载载体线程,持锁期间执行阻塞 I/O 仍有哪些风险

A 无风险
B 锁会失效
C 虚拟线程不会持锁
D 在原生调用等未覆盖路径上会钉住载体线程,降低吞吐 ✓ 正确答案
#

51. 非公平 ReentrantLock 的插队路径与公平锁的 hasQueuedPredecessors 检查如何影响吞吐和尾延迟

A 无锁
B 公平锁(FIFO 无饥饿) ✓ 正确答案
C 非公平锁
D 两者相同
#

52. Condition 在生产者-消费者中与 wait/notify 的等价转换与性能比较

A 不支持公平
B 精确唤醒(独立条件队列),避免 notifyAll 惊群 ✓ 正确答案
C 性能相同
D 只能唤醒一个
#

53. Condition 接口的精确唤醒与虚假唤醒

A 用 if 判断一次
B 加 sleep
C 忽略虚假唤醒
D await 返回后用 while 循环重新检查条件 ✓ 正确答案
#

54. Java 8 StampedLock 与内存序的细节

A 无保证
B state 版本号的 volatile 读写与 fence 保证的内存序 ✓ 正确答案
C 线程本地
D synchronized
#

55. Phaser 如何支持参与者动态注册和注销,忘记 arriveAndDeregister 会导致何种无法终止问题

A 抛异常自动恢复
B 后续阶段参与者计数不变,无法满足到达条件而无法推进 ✓ 正确答案
C 无影响
D 自动注销
#

56. Phaser 的注册表与阶段计数

A 记录线程优先级
B 记录超时时间
C 记录持有锁的线程数
D 记录当前阶段数,unarrived 归零时 phase 递增并重置未到达计数 ✓ 正确答案
#

57. StampedLock 的乐观读与失败重试模式

A 直接使用旧数据
B 忽略
C 重试乐观读或升级为悲观 readLock ✓ 正确答案
D 抛异常结束
#

58. Condition 的等待队列与 AQS 同步队列如何协作,signal 与 signalAll 的区别?

A signal 唤醒所有
B signal 唤醒条件队列的一个线程,signalAll 唤醒全部 ✓ 正确答案
C signalAll 只唤醒一个
D 无区别
#

59. JDK 25 中虚拟线程与 ReentrantLock 的协作及 JEP 491 后的残余钉住风险

A 普通 park
B synchronized 块内正常阻塞
C 外部原生方法调用(JNI)等 JVM 无法判定边界的路径 ✓ 正确答案
D ReentrantLock 等待
#

60. wait()/notify() 与 Condition 在生产者-消费者模式中的语义差异

A 不会虚假唤醒
B 性能总是更差
C 无需加锁
D 支持多个独立条件队列精确唤醒,避免 notifyAll 惊群 ✓ 正确答案
#

61. JDK 25 中 StampedLock 的乐观读模式在高读低写场景下的性能优势

A 写操作更快
B 与悲观读相同
C 读操作阻塞
D 读操作无锁、几乎无争用,吞吐高 ✓ 正确答案
#

62. StampedLock 的三种模式(写/悲观读/乐观读)在 JDK 25 中的内存语义

A 与写锁相同的互斥
B 完全不保证可见性
C 必须阻塞
D 不获取锁,可见性由 validate 校验版本号保证 ✓ 正确答案
#

63. 手写一个基于 AQS 的限流器(如 Semaphore 变体)需要考虑什么?

A 忽略取消
B 只重写 tryAcquire
C 保证 state 守恒(acquire/release 配对)与原子更新,并支持超时/中断 ✓ 正确答案
D 用独占模式