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

Java 并发包核心机制深度解析:锁的公平性、异步调度、AQS 原理全解


🧠 Java 并发包核心机制深度解析:锁的公平性、异步调度、AQS 原理全解

Java 并发编程的地基是 java.util.concurrent,但真正驱动这个系统的,是它背后隐藏的三根支柱:

  • ReentrantLock 的公平/非公平调度策略
  • CompletableFuture 的异步执行模型
  • AQS 的队列与阻塞线程管理机制

本文将以源码 & 结构视角解析这三块知识点,并配图讲清它们的运行状态与机制。


🔐 ReentrantLock 公平锁 vs 非公平锁

✳️ 概念区别

  • 公平锁(Fair):排队等待的线程会按顺序获取锁,避免“插队”。
  • 非公平锁(NonFair):新线程尝试直接 CAS 获取锁,如果成功就跳过队列 —— 提升吞吐量,但可能导致“饿死”。

📜 构造方式

// 默认是非公平锁
Lock lock = new ReentrantLock(); // 公平锁
Lock fairLock = new ReentrantLock(true);

⚙️ 实现原理

ReentrantLock 继承自 AbstractQueuedSynchronizer(AQS),关键方法如下:

// 非公平:直接尝试 CAS 抢锁
final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0 && compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}return false;
}// 公平:要先检查前面有没有排队线程
final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}return false;
}

🔁 锁状态图

[Free Lock] → tryAcquire()↓       ↘ (被占用)
[Acquired]   → 加入 AQS 等待队列 → LockSupport.park() 阻塞↓unlock() → 唤醒队列中的下一个线程

🚀 CompletableFuture 的异步调度机制

CompletableFuture 是 JDK 8 提供的函数式异步编程工具,常用于构建任务链和异步合并。

🧱 内部结构

CompletableFuture<T> {Object result;volatile Completion stack; // 任务链
}

每一个 thenApply, thenAccept, thenCombine 等方法,本质上是构建一个任务节点(Completion),放入队列中。

🔧 异步调度流程

CompletableFuture.supplyAsync(() -> {return 42;
}).thenApplyAsync(res -> {return res + 1;
});
  1. supplyAsync() 提交任务到默认线程池(ForkJoinPool.commonPool)
  2. 任务执行完成后,触发 postComplete(),依次唤醒后续 Completion
  3. 后续任务如果带 Async,会再次提交到线程池执行,否则同步调用

☑️ 核心调度代码

private void postComplete() {Completion h;while ((h = stack) != null) {if (UNSAFE.compareAndSwapObject(this, STACK, h, null))h.tryFire(NESTED);}
}

Completion 是内部静态类,代表任务节点链表,构成任务依赖树。


🧱 AQS:并发核心队列结构

AbstractQueuedSynchronizer 是整个 locks同步器 的基石,核心是管理同步状态与阻塞线程。

🧬 AQS 结构图

+-----------------------+
|     AbstractQueuedSynchronizer     |
+-----------------------+
| int state                          |
| Node head                          |
| Node tail                          |
+-----------------------+Node {Thread thread;Node next;Node prev;int waitStatus;  // SIGNAL, CANCELLED...
}

🔁 加锁过程(独占)

  1. 尝试获取锁(CAS 设置 state)
  2. 失败则入队(构造 Node,放入队列)
  3. 阻塞线程(LockSupport.park)
  4. 被唤醒后再次尝试获取锁

✨ 解锁过程

  1. CAS 修改 state,释放锁
  2. 唤醒队列中第一个 SIGNAL 状态的 Node(即下一个等待线程)
  3. 线程继续执行

🎯 总结:三者协作关系

模块角色底层依赖
ReentrantLock负责线程互斥、资源保护AQS + LockSupport
CompletableFuture异步任务链式调度ForkJoinPool + Completion
AQS管理线程队列、状态、阻塞机制CAS + LockSupport + Unsafe

## 🧩 附图:Java 并发包知识导图

相关文章:

  • 【MySQL】:数据库事务管理
  • JavaEE--2.多线程
  • 把dll模块注入到游戏进程的方法_基于文件修改的注入方式
  • MCP:AI时代的“万能插座”,开启大模型无限可能
  • SvelteKit 最新中文文档教程(22)—— 最佳实践之无障碍与 SEO
  • 进程与线程:02 多进程图像
  • 在统信UOS 1060上实现自动关机
  • 高防IP能抵御哪些类型的网络攻击?
  • Buildroot、BusyBox与Yocto:嵌入式系统构建工具对比与实战指南
  • 辛格迪客户案例 | 苏州富士莱医药GMP培训管理(TMS)项目
  • 深度学习3.3 线性回归的简洁实现
  • XXL-JOB 深入理解教程
  • 【MySQL】表的约束(主键、唯一键、外键等约束类型详解)、表的设计
  • javaSE.二叉查找树和平衡二叉树
  • EMQX安装使用和客户端认证
  • PCIE Spec ---Base Address Registers
  • 13 数据存储单位与 C 语言整数类型:从位到艾字节、常见整数类型及其范围、字面量后缀、精确宽度类型详解
  • 【嵌入式系统设计师(软考中级)】第二章:嵌入式系统硬件基础知识(上)
  • 玩转Docker | 使用Docker部署nullboard任务管理工具
  • 基于Python的图片/签名转CAD小工具开发方案
  • KZ队史首冠,透过春决看CF电竞张扬的生命力
  • 花3000元就能买“国际机构”的证书?揭秘假证产业链
  • 商务部:中国加快推进服务业扩大开放综合试点为世界注入更多确定性
  • 《上海国际金融中心进一步提升跨境金融服务便利化行动方案》印发
  • 深一度|上海半马,展示“体育+”无限可能的路跑狂欢
  • 从黄仁勋到美国消费者,都在“突围”