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

【juc第三章】:AQS机制全解

🔥你好我是fengxin_rou这是我的个人主页fengxin_rou的主页

❄️欢迎查看我的专栏我的专栏

《Java后端学习》、《JAVASE基础》、《JUC并发》、《redis》、《JVM虚拟机》、《MYSQL》、《黑马点评》、《rabbitmq》、《JavaWeb+AI的talis学习系统》、《苍穹外卖》

目录

前言:

AQS 是什么?核心设计思想?

AQS 底层结构:state 状态、双向阻塞队列?

AQS 独占模式、共享模式区别?

独占模式(Exclusive)

共享模式(Shared)

AQS 排队、唤醒线程的流程?

1、线程 排队(抢不到锁 → 进入等待)的流程

二、线程唤醒(释放锁 → 叫醒别人) 的流程

AQS为什么要用双向链表

1. 为了快速找到前驱节点(最核心原因)

2. 为了高效移除取消等待的线程节点

3. 为了保证队列不断裂

4. 为了精准唤醒下一个线程

总结


前言:

前面两篇学习了JUC并发的基础还有他的锁和关键字的知识,现在可以来了解一下JUC的底层框架AQS

AQS 是什么?核心设计思想?

AQS 全称AbstractQueuedSynchronizer(抽象队列同步器),是 Java 并发包(JUC)的底层核心框架,也是 ReentrantLock、Semaphore、CountDownLatch 等工具的统一基石。

AQS核心思想是,如果被请求的共享资源空闲,那么就将当前请求资源的线程设置为有效的工作线程,将共享资源设置为锁定状态;如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列

它提供了一些基本的操作,如acquire(获取资源)和release(释放资源),这些操作会修改state的值,并根据state的值来判断线程是否可以获取或释放资源。AQS 的acquire操作通常会先尝试获取资源,如果失败,线程将被添加到等待队列中,并阻塞等待。release操作会释放资源,并唤醒等待队列中的线程。

AQS 底层结构:state 状态、双向阻塞队列?

使用一个volatile state 变量表示锁状态:

state 是锁的属性,state=0表示资源空闲,线程可以抢占;state≠0表示资源被占用,线程无法直接获取。

底层维护一个 FIFO 双向链表队列:
抢不到锁的线程会被封装成节点,进入队列排队等待唤醒。

采用 CAS 无锁操作修改状态:

更新 state 时不需要使用 synchronized 加锁,而是通过CAS 原子指令实现无锁、安全、高效的更新。

AQS 独占模式、共享模式区别?

独占模式(Exclusive)

一句话:只有一个线程能拿到锁,其他人必须等。

  • 同一时刻只能有一个线程获取资源
  • state被占用后,其他线程不能获取,state = 0才能拿资源
  • 线程获取:tryAcquire
  • 线程释放:tryRelease
  • 典型实现:ReentrantLock、读写锁的写锁
  • 用途:写操作、修改数据、保证线程安全

共享模式(Shared)

多个线程可以同时拿到资源,一起执行。

  • 同一时刻允许多个线程同时获取资源
  • state代表可用数量,只要 >0 就能拿
  • 线程获取:tryAcquireShared
  • 线程释放:tryReleaseShared
  • 典型实现:Semaphore、CountDownLatch、读写锁的读锁
  • 用途:读操作、限流、多线程等待

AQS 排队、唤醒线程的流程?

1、线程 排队(抢不到锁 → 进入等待)的流程

  1. 线程来抢锁,先去CAS 修改 state
  2. 修改成功:拿到锁,直接执行业务代码
  3. 修改失败:锁被别人占用,不能拿锁
  4. 把当前线程封装成一个Node 节点
  5. 把节点加入双向队列的尾部
  6. 检查前面的节点是否正常
  7. 确认安全后,调用LockSupport.park()
  8. 线程进入阻塞(挂起),不再运行,等待唤醒

二、线程唤醒(释放锁 → 叫醒别人) 的流程

  1. 拿到锁的线程执行完毕
  2. 调用释放方法,把 state 恢复为 0
  3. 去队列里找到头节点的下一个有效线程
  4. 调用LockSupport.unpark()唤醒这个线程
  5. 被唤醒的线程退出阻塞
  6. 再次去CAS 抢 state
  7. 抢成功 →成为新的头节点,开始执行业务
  8. 执行完再释放,继续唤醒下一个

AQS为什么要用双向链表

1. 为了快速找到前驱节点(最核心原因)

线程在阻塞前,必须检查前面一个节点的状态,判断自己是否可以安全挂起。

  • 双向链表有prev指针,可以直接获取前驱节点
  • 单向链表没有向前的指针,无法快速找到前一个节点。

所以必须用双向链表,才能实现安全阻塞逻辑


2. 为了高效移除取消等待的线程节点

如果线程等待超时、或被中断,需要从队列中删掉自己

  • 双向链表:直接通过prevnext把自己从队列摘除,O (1) 效率
  • 单向链表:必须从头遍历找到前驱,效率极低

高并发下大量线程取消等待,双向链表是唯一选择


3. 为了保证队列不断裂

高并发入队、出队时,单向链表很容易出现指针丢失,导致队列断裂。 双向链表有前后双向指针互相兜底,即使某一个指针异常,队列依然完整。


4. 为了精准唤醒下一个线程

AQS 唤醒规则是:唤醒头节点的下一个节点

  • 双向链表通过next能立刻找到下一个等待线程。
  • 单向链表无法快速找到后继,唤醒效率低。

总结

  • 快速找到前驱节点,保证线程安全阻塞
  • 高效移除取消、中断、超时的节点
  • 高并发下防止队列断裂,提高稳定性;
  • 快速找到后继节点,实现精准唤醒

http://www.jsqmd.com/news/907866/

相关文章:

  • 大语言模型在糖尿病管理中的应用:架构、场景与挑战
  • 如何用Python快速接入Taotoken并调用多款大模型API
  • 2026年知名的赣州泡沫柱/泡沫垫/泡沫粒/泡沫板实力工厂推荐 - 品牌宣传支持者
  • 保姆级教程:用Docker Buildx搞定ARM和x86镜像,一键推送到自建私有仓库
  • GazeProphet:无硬件依赖的VR注视点预测技术解析
  • 无线网络自动规划中的多目标优化:挑战、算法与工程实践
  • 告别环境配置噩梦:用最新方法在Ubuntu 20.04快速部署PX4与ROS1开发栈
  • Easypoi停更了怎么办?手把手教你平滑迁移到Apache Fesod(附模板导出对比)
  • 仅限首批200名开发者获取:Gemini正则智能生成器Beta版+12个行业专用Pattern库(含医疗/金融/日志解析)
  • 2026年5月抛丸机厂家推荐:TOP5排行专业评测重工行业清理效率高价格特点 - 品牌推荐
  • YOLOv5模型对比实战:COCO128上训练的小模型 vs. 官方预训练大模型,效果差多少?
  • 纳米级DSIP架构设计:突破AI芯片互连瓶颈
  • 2026年评价高的仓储货架/苏州悬臂式货架/模具货架优质公司推荐 - 品牌宣传支持者
  • 量化团队风险:从巴士因子到可执行的韧性评估框架
  • 告别Circos?试试用ggplot2轻松绘制多组学突变在染色体上的分布热图
  • AcWing 2236:伊基的故事 I - 道路重建 ← 最大流之关键边 + Dinic算法
  • PyTorch Geometric (PyG) 安装避坑全记录:从依赖冲突到版本匹配的保姆级教程
  • ArcGIS Pro 3.0 保姆级教程:从零开始,5分钟搞懂地图和场景的区别与选择
  • 独立游戏开发实战:基于Godot引擎的Roguelike游戏设计与实现
  • 2026年评价高的羽衣甘蓝粉代餐/羽衣甘蓝粉代加工推荐厂家精选 - 行业平台推荐
  • 【AI大模型应用开发工程师特训笔记】第04讲(第8章):面向对象编程
  • 2026南通驾校推荐榜:C1/C2/D/E 证培训、摩托车驾培、机器人教学驾校多维解析 摘要 - 海棠依旧大
  • 2025-2026年上海吉日搬场有限公司电话查询:选择搬场服务前需核实资质与合同条款分析 - 品牌推荐
  • 从助焊膏选择到焊后清理:一次搞懂QFN芯片手工焊接的全流程避坑要点
  • 知识嫁接技术:突破边缘AI部署瓶颈的新方法
  • C51数学函数性能优化与嵌入式开发实践
  • 从《绝地求生》到《原神》:盘点那些用虚幻引擎和Unity 3D打造的现象级PC游戏
  • AI电台主持人系统架构:从情感语音合成到实时交互的工程实践
  • 2026年质量好的山东微型千类轴承/高速千类轴承/替代进口千类轴承/精密千类轴承实力工厂推荐 - 品牌宣传支持者
  • 保姆级教程:在CentOS 7.9上用OpenStack All-in-One搞定虚拟机上网(附浮动IP配置)