2026年01月21日/ 浏览 5
在Java的并发王国里,synchronized 关键字如同世袭的贵族,凭借语言层面的原生支持享有盛名。而
AQS(
AbstractQueuedSynchronizer) 和 CAS(Compare-And-Swap) 则更像两位深藏不露的民间宗师,他们不事声张,却用一套精妙的“生存法则”,默默支撑起 ReentrantLock、Semaphore 等强大工具的运作。余华在《活着》中写道:“人是为了活着本身而活着,而不是为了活着之外的任何事物所活着。” AQS与CAS的底层逻辑,也蕴含着同样的纯粹——它们的全部目的,就是让多线程在激烈的资源竞争中,能够安全、有序地“活着”。
今天,让我们超越API的表象,深入这场关于秩序与竞争的底层博弈。
在没有CAS的混沌时代,多线程对变量的修改犹如一场无规则的哄抢。而CAS的引入,确立了一条简单的原子契约:“我认为值现在是A,如果是,我就把它改为B;如果不是,说明已被他人修改,我则放弃重试。”
1. 核心机制:一条不可分割的CPU指令
CAS操作是CPU提供的一条硬件级原子指令,其逻辑决绝,没有中间状态。它依赖三个操作数:
内存地址(V):需要更新的变量位置。预期原值(A):线程认为变量当前的值。新值(B):线程希望设置的值。当CPU执行CAS指令时,它会先比较地址V处的实际值是否等于A。若相等,则原子性地将值更新为B;若不相等,则不做任何操作。无论成功与否,它都会将结果告知调用者。
2. Java中的实现:Unsafe类的硬核操作
在Java中,这一能力通过 sun.misc.Unsafe 类提供,它如同一个通往底层世界的“后门”。其核心方法签名清晰地反映了这一契约:
// 核心CAS方法:如果对象o中偏移量为offset的int值等于expected,则原子性地更新为x public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);生活化比喻:这就像在图书馆借阅一本孤本书。线程A执行CAS的流程是:
查看(Compare):我看到书《Java并发实战》(V)还在书架上(A=在架)。交换(Swap):如果书确实在,我将其借走(B=借出)。原子性:“查看”和“借走”是一个不可分割的动作,确保在我看到书在架后,不会被其他人抢先借走。3. 优势与代价:乐观锁的双面性
优势(避免挂起):这是一种乐观锁策略。它假设竞争不总是发生,因此不像synchronized那样直接挂起线程,避免了昂贵的线程上下文切换开销。代价与解决方案:ABA问题:书被借出(B)后又归还(A),线程A的CAS会误以为书从未被动过。解决方案是使用AtomicStampedReference添加“版本号”。自旋开销:竞争激烈时,大量线程会循环重试(自旋),空耗CPU。解决方案是限制自旋次数或让线程优雅地暂停。如果说CAS是原子性的“单点契约”,那么AQS就是基于这份契约,构建起一整套复杂的“排队与调度规则”的框架。它是并发工具背后的“万能骨架”。
1. 两大核心组件:状态与队列
AQS的内部,是一个精巧而高效的管理系统:
状态变量(volatile int state):这是系统的“状态牌”,其语义由子类定义。在 ReentrantLock 中,state 表示锁的持有计数(0=空闲,≥1=被持有)。在 Semaphore 中,state 表示可用许可证的数量。等待队列(CLH变体):这是一个FIFO的双向链表。所有争夺资源失败的线程,都会被封装成节点,在此排队等待。这是秩序的关键。比喻升级:AQS就像一个高效的银行大堂经理。
状态变量(state):经理身边那个显示“当前受理号码”的电子屏。等待队列:客户拿号后排成的队伍。CAS操作:经理叫号时,核对“当前号码”与客户“手中号码”是否一致的原子动作。3. 核心工作流程:获取、排队、释放
获取资源(tryAcquire):线程(客户)到来,尝试通过CAS修改state(尝试直接办理业务)。成功则继续执行。入队等待(addWaiter & acquireQueued):若CAS失败(柜台正忙),线程会被封装成节点,通过CAS操作安全地加入队列尾部(取号排队)。队列中的线程会暂停(LockSupport.park())以避免空转,等待被唤醒。释放与唤醒(release):持有资源的线程(办完业务的客户)释放资源(修改state),然后唤醒(LockSupport.unpark())队列中的下一个线程(叫下一个号)。4. 强大的抽象:定义同步器的模板
AQS的强大在于,它用模板方法模式将复杂的排队/唤醒逻辑封装好,子类只需根据特定语义实现几个 protected 方法(如 tryAcquire、tryRelease)即可。这正是 ReentrantLock、CountDownLatch 等工具实现各异但内核统一的根源。
它们的关系是层次分明、相互依存的:
CAS是AFS的“原子砖石”:AQS中所有对state的修改和队列节点的操作,其原子性都依赖于CAS。没有CAS,AQS的秩序无从谈起。AQS是CAS的“智慧升华”:CAS本身只能管理“一个点”的原子性。AQS则利用CAS,构建了管理“一个面”(多线程排队调度)的复杂规则。它将CAS的能力放大了数个量级。理解AQS与CAS,远不止为了面试。其价值在于:
精准排查问题:当遇到锁饥饿、性能瓶颈等复杂并发问题时,你能直指核心,而非在API层面盲目尝试。做出高明设计:你能真正理解不同工具(如ReentrantLock vs synchronized)的成本与收益,从而在架构设计上做出最佳选择。建立并发思维:这种在竞争中对“原子性”的敬畏、在冲突中对“秩序”的构建,是一种普适的解决复杂系统问题的思维模型。结语
并发世界的底层,没有魔法。有的只是如CAS般“乐观尝试,失败重来”的坚韧,和如AQS般“维护状态,有序排队”的规则。这套最硬核的逻辑,恰恰藏着最实用的生存智慧:在竞争中积极争取,在规则中耐心等待。