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

深入解析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 实现读写锁),欢迎继续提问!

http://www.cnnetsun.cn/news/421947.html

相关文章:

  • GLM-TTS在医疗场景的应用设想:病历语音记录辅助
  • 【高并发系统稳定性保障】:PHP与Redis缓存同步的7大陷阱与规避方法
  • 区块链+PHP=无敌数据安全?深度剖析5大加密瓶颈与突破路径
  • 【数据防泄漏终极方案】:基于PHP的区块链加密落地实践
  • 从可用到好用:一体机助力数据库国产化应对性能考验
  • R语言遇上GPT:构建智能清洗管道的7个关键步骤(附完整代码)
  • GLM-TTS与Ghost CMS结合:专注于内容发布的平台集成
  • 简单理解:电平翻转,是 QSPI 通信的核心机制—— 本质是通过引脚高低电平(0/1)的快速切换,实现 “数据 / 命令 / 地址的传输”
  • 单片机Flash高效烧写
  • 如何用GLM-TTS生成电商平台的商品介绍语音
  • 面试必杀:什么是 ‘LangGraph Cloud’ 的底层优势?探讨它在处理长周期(Persistent Threads)任务时的独门秘籍
  • [特殊字符]开题报告卡壳退退退!虎贲等考 AI 解锁学术开题 “加速器”[特殊字符]
  • GLM-TTS在跨境电商中的应用:多语言商品描述语音化
  • 【PHP高性能文件传输指南】:从零构建支持断点续传的大文件下载系统
  • 为什么你的PHP系统需要区块链加密?这4个真实案例让你彻底明白
  • 使用Docker部署GLM-TTS并挂载网盘直链下载助手实现数据互通
  • opencode:vide coding工具安装介绍;使用案例
  • python白优校园社团网站的设计与实现论文_93wlp--(flask django Pycharm)
  • Springboot vue医院健康体检系统
  • 【Web实时通信安全指南】:用PHP实现WebSocket TLS+AES双重加密
  • GLM-TTS参考文本留空的影响测试:是否真能自动识别内容
  • 仅限内部分享:PHP解析自定义物联网协议的逆向工程秘技(限时公开)
  • GLM-TTS与Notion API集成:实现文档到语音的自动转换
  • GLM-TTS能否用于地震预警系统?黄金10秒语音倒计时广播
  • 如何将GLM-TTS集成到Web应用?JavaScript前端调用方案探索
  • 语音合成创业项目落地:以GLM-TTS为核心提供定制化服务
  • LTC3633替代芯片AH3633E/X:20V/3A同步降压DCDC稳压器
  • ultralytics-yolo11中如何修改预测的矩形框和矩形框上面文字的粗细?
  • 语音合成与数字永生关联:为逝者保存永久声音记忆
  • 语音合成中的跨语种发音迁移:中文母语者说英文口音控制