当前位置: 首页 > news >正文

AQS与CAS深度讲解

下面我给你 一口气把 AQS 与 CAS 讲透。你有十年 Java 经验,我直接按“面试+底层原理+源码模型”这种工程师能秒懂的方式来讲,不整花里胡哨的。


🔥 一、CAS:并发世界的基石(Compare-And-Swap)

1. CAS 是什么?

一句话:CAS = 无锁原子操作

它做三件事:

CAS(V, E, N):如果 V == E,则把 V 设置为 N,返回 true否则不修改 V,返回 false
  • V:内存地址中的当前值
  • E:期望值
  • N:更新后的新值

谁提供 CAS?
➡ JVM 通过 Unsafe.compareAndSwapXxx() 调用 CPU 指令(x86 的 CMPXCHG
➡ CPU 保证这是“原子的”、线程安全的。

你可以认为 CAS = 硬件级别的乐观锁


2. CAS 的三大问题(面试高频)

✔ 1. ABA 问题

值从 A → B → A,CAS 觉得没变,但其实中间变化过。

解决:

  • AtomicStampedReference(时间戳)
  • AtomicMarkableReference(标记位)

✔ 2. 自旋开销

失败后一直循环重试,导致 CPU 空转。

JDK 做过很多优化:

  • 自适应自旋(spin count 会动态调整)
  • 在锁高竞争时减少自旋

✔ 3. 只能保证一个变量的原子性

要保证多个变量的一致性?
➡ 只能用锁(synchronized / ReentrantLock)。


🔥 二、AQS:Java 锁的地基(AbstractQueuedSynchronizer)

ReentrantLock / Semaphore / CountDownLatch / ReentrantReadWriteLock / FutureTask 都是基于 AQS 实现的。
它是整个 JUC 的地心引力。


1. AQS 的核心思想 — “CLH 双向队列 + CAS 改 state”

AQS 有两个关键点:

✔(1)一个共享变量:state

表示锁是否被持有:

  • 对于 ReentrantLock:
    state = 0 → nobody hold
    state > 0 → 被 hold 并记录重入次数

  • 对于 Semaphore:state = 当前许可数

  • 对于 CountDownLatch:state = 计数

修改 state 时用 CAS


✔(2)一个 FIFO 阻塞队列:CLH(变体)

AQS 内部维护一个双向链表:

head <-> node1 <-> node2 <-> node3 ...

每个 Node 表示一个线程的排队信息:

  • 前驱
  • 后继
  • 等待状态(SIGNAL / CANCELLED / CONDITION)

线程抢锁失败时就会加入这个队列,并在必要时挂起(park)。

这就是“排队 + 挂起 + 唤醒”的核心机制。


🔥 三、AQS 的 acquire() 流程(独占锁)

以 ReentrantLock(非公平锁)为例:

1)尝试 CAS 抢锁

if (compareAndSetState(0, 1)):成功 → 把当前线程设为独占 owner,返回

2)失败 → 入队

加入 CLH 队列尾部

3)进入循环

只要你不是队列头结点的下一个线程,你就继续 park(阻塞)。

4)等待前驱线程释放锁后唤醒

解锁时会:

state = 0
唤醒队列中第一个有效节点

5)被唤醒后再次尝试 CAS 抢锁

如果抢到,成功;否则继续阻塞。


🔥 四、AQS 的 release()(解锁流程)

  1. CAS 减少 state(可重入锁会减到 0 才真正释放)

  2. 如果 state == 0

    • 唤醒队列中的第一个节点(unpark)
  3. 被唤醒的线程再次尝试 CAS 抢锁

整个 AQS 都是“CAS 重试 + park 阻塞 + unpark 唤醒”组成。


🔥 五、公平锁 vs 非公平锁(面试必问)

✔ 非公平锁

先 CAS 抢一次锁,没抢到再排队。
好处:吞吐更高

✔ 公平锁

必须排队,不允许插队。

公平锁流程:

if (没有排队 && state == 0):CAS(0,1)

非公平锁:

CAS(0,1) // 插队

这是它们最关键的区别。


🔥 六、AQS 为什么这么强?

因为它把“加锁/解锁的通用逻辑”抽象出来

  • 排队
  • 阻塞/唤醒
  • CAS 管理 state

然后“子类”只需实现两个方法:

tryAcquire()
tryRelease()

比如 ReentrantLock 实现的就是:

tryAcquire():if (state == 0)CAS(0,1)else if (当前线程 == owner)state++
tryRelease():state--if state == 0:owner = null

CountDownLatch:

tryAcquire()    直接失败
tryRelease()    state-- 到0则唤醒等待线程

Semaphore:

tryAcquire():  state-- >= 0?
tryRelease():  state++

AQS = 队列 + 线程挂起 唤醒机制
锁类 = 定义自己如何修改 state

完美分层。


🔥 七、总结(超快记忆版)

🧱 CAS:

  • 基于 CPU 指令
  • 乐观锁
  • ABA / 自旋问题
  • 修改单变量

🏗 AQS:

  • CLH 双向队列 + CAS 修改 state
  • ReentrantLock / Semaphore / CountDownLatch 的基石
  • acquire/release 模型
  • park/unpark 控制线程

一句话:CAS 是原子性;AQS 是并发框架。

http://www.gsyq.cn/news/79856.html

相关文章:

  • PKU 数据结构与算法 2025 复习题 坐公交
  • CF1046I Say Hello - crazy-
  • Python 函数与 lambda 表达式的结合
  • 中小企业走向境外资本市场:境外上市辅导、美股上市实践与中国境外券商投行机构角色——以顺安资本为例
  • 2025年12月佛山二手房拍卖机构标杆推荐:佛山房屋拍卖推荐佛山市中正易拍拍卖有限公司
  • 第五十七篇
  • 2025年唐老狮:游戏开发教育商业模式深度解析与性价比评估
  • 2025年12月河南驻马店气体配送优质厂家推荐:河南宏源气体,氧气气体配送、氮气气体配送、氦气气体厂家、二氧化碳气体配送、氩气气体公司、高纯气体配送、多品类气体供应新标杆
  • 2025年唐老狮:游戏开发课程体系全景解析与行业应用价值深度评估
  • 链路追踪基础SkyWalking/Zipkin认知与分布式系统问题定位实战
  • 2025年12月东营搬家公司推荐:双福搬家,东营搬家搬厂、东营河口搬家、东营垦利搬家、东营市搬家、东营单位搬家、东营设备搬运、全场景搬迁服务标杆
  • PROFILE
  • 2025年12月阳光房遮阳棚优质厂家推荐,电动凉亭遮阳棚、防风帘遮阳棚、防蚊帘遮阳棚、小型遮雨棚、移动遮雨棚、金属遮雨棚、聚焦舒适节能解锁惬意户外空间
  • 完整教程:MySQL 全体系深度解析(存储引擎、事务、日志、MVCC、锁、索引、执行计划、复制、调优)
  • 2025年热门的流延机设备/高分子材料流延机厂家最新权威推荐排行榜
  • 2025年热门的铝合金隔热条厂家推荐及采购指南
  • 2025年口碑好的电热水袋/防爆热水袋厂家最新用户好评榜
  • 完整教程:Vue-Loader 深度解析:原理、使用与最佳实践
  • #题解#洛谷P1045 麦森数#快速幂#高精度乘法#
  • 一类通过寻找区间关键点从而弱化子区间的限制而优化复杂度的问题
  • C++之函数(六) - Invinc
  • 2025 雅思报班不踩雷!高口碑机构红榜 + 3 类考生适配指南
  • 雅思培训机构怎么选?2025年这5家高性价比机构值得关注
  • 2025年口碑好的双胞胎婴儿车国货
  • vue-dawn-flow 低代码流程插件
  • 百日挑战——单词篇(第二十天) - 指南
  • 洛谷U639786 树的颜色询问 题解 树上启发式合并(dsu on tree)
  • Webpack与Vite的常用设置及主要差异分析
  • 2025 年雅思培训口碑机构 TOP5 推荐
  • 2025年质量好的平版胶印油墨/胶印油墨厂家最新热销排行