AQS通过自旋+ CAS减少首轮阻塞、同步队列按需唤醒、支持多种等待策略及避免锁升级开销,显著降低不必要的上下文切换。

AQS(AbstractQueuedSynchronizer)本身不直接“解决”上下文切换开销,而是通过设计机制**显著减少不必要的切换**,尤其在竞争激烈时避免线程盲目挂起与唤醒。它的核心思路不是消除切换,而是让切换更可控、更稀疏、更有价值。
用自旋 + CAS 减少首轮阻塞
当线程尝试获取锁(如 ReentrantLock.nonfairTryAcquire)时,AQS 先执行一次或多次 CAS 操作抢占资源。成功则直接进入临界区,全程无切换;失败也不立即挂起,而是进入同步队列前可能做短时自旋(尤其在非公平模式下)。这种“先抢后等”的策略,把大量轻度竞争消解在用户态,避免了内核态切换的昂贵开销。
同步队列按需唤醒,杜绝无效调度
AQS 维护一个 FIFO 双向链表(CLH 变种),只有前驱节点释放锁时,才精准唤醒后继节点。这带来两个关键收益:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 不会出现“广播式唤醒”(比如 notifyAll),避免多个线程同时争抢锁、全部失败再重新挂起的雪崩式切换
- 被唤醒的线程大概率能立即获得资源,减少了“唤醒即阻塞”的空转切换
支持多种等待策略,适配不同竞争强度
AQS 提供了灵活的节点状态(CANCELLED、SIGNAL、CONDITION 等)和 park/unpark 原语,使得上层同步器可定制行为:
立即学习“Java免费学习笔记(深入)”;
- ReentrantLock 非公平模式:允许新线程插队,降低长尾延迟,也减少队列积压引发的大规模唤醒
- Semaphore 公平模式虽牺牲吞吐量,但通过严格排队抑制了线程反复抢锁-失败-重试的震荡循环,反而稳定了切换频率
- CountDownLatch/CyclicBarrier 在 await 时若条件未满足,线程才进入条件队列;条件满足后批量 unpark,集中处理,而非逐个唤醒
避免锁升级带来的隐式切换放大
对比 synchronized 的重量级锁(依赖操作系统互斥量),AQS 实现的锁始终由 JVM 自主管理。即使竞争激烈导致线程阻塞,其 park/unpark 调用仍比传统 wait/notify 更轻量,且不触发偏向锁撤销、锁膨胀等额外开销——这些环节在 synchronized 中会引发 stop-the-world 或全局锁竞争,间接加剧上下文切换压力。

















