news 2026/6/1 5:30:33

深入解析AQS:Java并发基石

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入解析AQS:Java并发基石

🔑 一、AQS 是什么?——“同步器的骨架”

AQS = AbstractQueuedSynchronizer
它是一个抽象类,提供了一套基于 FIFO 阻塞队列 + 原子状态管理的框架,让你能轻松实现各种自定义的同步工具。

✅ 核心能力:

  1. 管理一个整型状态(state:表示资源是否可用(如锁是否被占用、计数器剩余值等)。
  2. 维护一个 FIFO 等待队列:当线程获取资源失败时,自动入队并阻塞;释放资源时,唤醒队列中的下一个线程。
  3. 支持独占模式(exclusive)和共享模式(shared)
    • 独占:同一时刻只能一个线程持有(如ReentrantLock)。
    • 共享:多个线程可同时持有(如SemaphoreCountDownLatch)。

💡AQS 本身不定义“同步语义”,而是把“如何判断能否获取资源”、“如何释放资源”这些逻辑留给子类实现


🧱 二、AQS 的核心机制

1.状态管理(State)

  • 通过volatile int state表示同步状态。
  • 提供三个方法操作它:
    protectedfinalintgetState()protectedfinalvoidsetState(intnewState)protectedfinalbooleancompareAndSetState(intexpect,intupdate)// CAS
  • 子类通过这个state来表达自己的业务含义:
    • ReentrantLock:0=未锁,1=已锁(重入次数)
    • Semaphore:表示剩余许可数量
    • CountDownLatch:表示倒计数值

2.FIFO 等待队列(CLH 变种)

AQS 使用一个双向链表(Node 链表)来管理等待线程:

head → [Node1] ↔ [Node2] ↔ [Node3] ← tail

每个Node包含:

  • thread:等待的线程
  • waitStatus:节点状态(如SIGNAL=-1表示需要被唤醒)
  • prev/next:前后指针
  • nextWaiter:用于区分是独占还是共享模式(或用于 Condition)

⚠️ 注意:这是一个CLH 队列的变种,原始 CLH 用于自旋锁,而 AQS 用于阻塞锁,所以增加了next指针便于唤醒后继。


3.两种模式:独占 vs 共享

模式方法说明
独占(Exclusive)tryAcquire()
tryRelease()
成功则获得排他权限(如写锁)
共享(Shared)tryAcquireShared()
tryReleaseShared()
返回值 ≥0 表示成功,可多线程并发(如读锁、信号量)

🔄 共享模式下,释放资源时可能级联唤醒多个线程(因为多个线程可能同时满足条件)。


🧩 三、关键流程解析

▶ 获取资源(以独占为例)

publicfinalvoidacquire(intarg){if(!tryAcquire(arg)&&acquireQueued(addWaiter(Node.EXCLUSIVE),arg))selfInterrupt();}
  1. 先尝试tryAcquire()(由子类实现)。
  2. 如果失败,调用addWaiter()将当前线程封装成Node加入队尾。
  3. 调用acquireQueued():在队列中自旋,直到被前驱唤醒且自己成为头节点后再次尝试获取。

▶ 释放资源(独占)

publicfinalbooleanrelease(intarg){if(tryRelease(arg)){// 子类实现Nodeh=head;if(h!=null&&h.waitStatus!=0)unparkSuccessor(h);// 唤醒后继returntrue;}returnfalse;}
  • 成功释放后,调用unparkSuccessor()唤醒下一个等待线程。

🔍unparkSuccessor()会从tail往前找第一个非取消的节点(处理中间节点被中断/超时的情况)。


🛠️ 四、如何使用 AQS?——子类必须实现的方法

不能直接使用 AQS,而是继承它并实现以下方法(根据需求选):

方法用途必须实现?
tryAcquire(int)独占式获取是(如果支持独占)
tryRelease(int)独占式释放
tryAcquireShared(int)共享式获取是(如果支持共享)
tryReleaseShared(int)共享式释放
isHeldExclusively()当前线程是否独占持有是(如果要用Condition

✅ 所有这些方法都必须是无阻塞、线程安全、短小精悍的!


📌 五、经典例子回顾

例1:非重入互斥锁(Mutex)

staticclassSyncextendsAbstractQueuedSynchronizer{protectedbooleantryAcquire(intacquires){if(compareAndSetState(0,1)){setExclusiveOwnerThread(Thread.currentThread());returntrue;}returnfalse;}protectedbooleantryRelease(intreleases){setState(0);setExclusiveOwnerThread(null);returntrue;}protectedbooleanisHeldExclusively(){returngetState()==1;}}

例2:一次性门闩(BooleanLatch)

staticclassSyncextendsAbstractQueuedSynchronizer{protectedinttryAcquireShared(intignore){returngetState()==1?1:-1;// 1=已触发,-1=需等待}protectedbooleantryReleaseShared(intignore){setState(1);returntrue;// 唤醒所有等待者}}

🌟 六、高级特性

1.公平性控制

  • 默认是非公平的(允许“插队”:新线程可能在排队线程之前抢到锁)。
  • 实现公平锁:在tryAcquire中加判断:
    if(hasQueuedPredecessors())returnfalse;// 有排队者就别插队

2.Condition 支持

  • 通过new ConditionObject()创建条件变量。
  • 必须实现isHeldExclusively()和正确的release/acquire逻辑。

3.可中断、超时支持

  • AQS 提供了acquireInterruptiblytryAcquireNanos等方法,子类只需调用即可。

✅ 总结:AQS 的设计哲学

“Don’t call us, we’ll call you.” — Hollywood Principle

  • AQS 负责:队列管理、线程阻塞/唤醒、状态原子性、中断/超时处理
  • 你(子类)负责:定义“什么是获取成功”、“什么是释放成功”

这使得你可以用几十行代码实现出工业级的同步器,而无需操心底层并发细节。


如果你正在学习 JUC 或想深入理解ReentrantLockSemaphore等的原理,掌握 AQS 是必经之路。它的设计堪称 Java 并发编程的“皇冠上的明珠”。

如需进一步分析某个具体同步器(比如ReentrantReadWriteLock如何用 AQS 实现读写锁),欢迎继续提问!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/30 23:10:18

GLM-TTS与Storyblok集成:体验驱动的内容管理

GLM-TTS与Storyblok集成:体验驱动的内容管理 在今天的数字内容生态中,用户不再满足于“只读”的静态信息。他们希望听到声音、感受情绪、获得沉浸式的交互体验。尤其是在教育、媒体和电商领域,语音内容正从“附加功能”演变为“核心交付形式…

作者头像 李华
网站建设 2026/5/30 23:10:20

GLM-TTS能否支持实时直播配音?低延迟传输挑战

GLM-TTS 能否用于实时直播配音?低延迟挑战的深度解析 在虚拟主播、游戏解说和在线教育日益普及的今天,用户对“输入即发声”的语音合成体验提出了更高要求。传统文本到语音(TTS)系统往往需要等待完整文本输入后才开始生成音频&…

作者头像 李华
网站建设 2026/5/30 18:10:15

如何用GLM-TTS生成YouTube视频配音并规避版权风险

如何用GLM-TTS生成YouTube视频配音并规避版权风险 在内容为王的时代,一个YouTube频道的成败,往往不只取决于画面剪辑和脚本质量,更在于声音是否“抓耳”。许多创作者曾面临这样的困境:使用商业TTS服务,音色千篇一律&am…

作者头像 李华
网站建设 2026/5/28 21:15:55

为什么你的PHP下载接口撑不过100MB?:必须掌握的4个底层机制

第一章:为什么你的PHP下载接口撑不过100MB? 当你在开发一个文件下载功能时,可能会发现小文件传输毫无压力,但一旦文件超过100MB,服务器就出现超时、内存溢出甚至直接崩溃。这背后的核心原因往往不是网络带宽&#xff0…

作者头像 李华
网站建设 2026/5/29 2:13:42

GLM-TTS语音情感控制原理剖析:如何通过样本传递情绪

GLM-TTS语音情感控制原理剖析:如何通过样本传递情绪 在虚拟主播动辄百万粉丝、AI配音悄然渗透影视制作的今天,一个关键问题正被反复追问:机器能否真正“动情”地说话? 我们早已厌倦了那种字正腔圆却毫无波澜的朗读式合成音。用户…

作者头像 李华
网站建设 2026/5/28 23:53:06

VT25-373-99/X9直流转换器

VT25-373-99/X9 直流转换器概述 这款模块属于工业级直流电源转换设备,主要用于将一定范围的直流输入电压转换为稳定、可用的直流输出电压,为各种电子控制系统、仪器仪表、通信设备或自动化设备提供可靠电源支持。主要功能与特点输入/输出性能支持宽输入电…

作者头像 李华