JUC
一、并发的第一性问题空间(Why 并发工具存在)
所有 Java 并发工具,本质上都在解决有限计算资源在多执行主体之间的分配与协调问题。
从第一性原理出发,并发系统只存在五类不可约的问题:
1. 互斥(Mutual Exclusion)
- 同一时刻,**共享资源只能被一个线程修改**
- 本质冲突:写-写、读-写冲突
2. 可见性(Visibility)
- 一个线程对共享状态的修改,**何时、如何被其他线程观察到**
3. 协调(Coordination)
- 多个线程之间需要**在时间或阶段上达成一致**
- 不是竞争,而是协作
4. 资源限流(Throttling)
- 资源有限(连接、线程、IO),需要控制**同时访问者数量**
5. 上下文隔离与传播(Context Management)
- 并发执行下,如何**安全地保存、传递线程上下文**
所有 JUC 工具,都可以被映射回上述问题之一或组合。
二、Java 并发的总体架构分层(How Java 解决并发)
并发问题空间 ↓并发抽象模型(锁 / 同步器 / 限流器 / 上下文) ↓并发框架(AQS) ↓具体工具类(ReentrantLock / Semaphore / CountDownLatch ...)这一分层体现了 稳定性递增原则:
- 越靠上,越接近不变原理
- 越靠下,越接近实现细节
三、AQS:Java 并发的“内核抽象”
3.1 AQS 的设计哲学
AQS(AbstractQueuedSynchronizer)并不是“锁”,而是:
竞争失败线程的统一管理框架
它抽象了并发控制中最稳定的三件事:
- **资源状态(state)**:资源是否可用
- **等待队列(FIFO)**:竞争失败者排队
- **阻塞 / 唤醒机制**:最小化 CPU 空转
3.2 AQS 的核心模型
state(int) → 资源状态机同步队列(CLH变体) → 管理竞争失败线程条件队列 → 管理协作型等待AQS 通过模板方法模式,将策略交给子类:
- tryAcquire / tryRelease
- tryAcquireShared / tryReleaseShared
而将调度、排队、阻塞统一托管。
四、互斥问题:ReentrantLock 与 synchronized
4.1 抽象模型
- **互斥锁 = 状态机 + 排队规则**
- 可重入性本质:**线程身份绑定 + 计数状态**
4.2 公平性:一种资源分配哲学
| 策略 | 价值取向 | 代价 |
|---|---|---|
| 公平锁 | 顺序正义 | 吞吐下降 |
| 非公平锁 | 系统效率 | 局部饥饿 |
公平性不是技术问题,而是系统价值判断。
4.3 synchronized vs ReentrantLock
| 维度 | synchronized | ReentrantLock |
|---|---|---|
| 实现层 | JVM | JDK |
| 锁释放 | 自动 | 手动 |
| 公平性 | 非公平 | 可配置 |
| 中断 | 不支持 | 支持 |
工程哲学:
能用 synchronized,就不要用 Lock。
五、读写分离:ReentrantReadWriteLock 与 StampedLock
5.1 读写锁的核心矛盾
- **读多写少**是常态
- 写操作必须独占
- 读操作应最大化并发
5.2 ReentrantReadWriteLock
- 悲观并发模型
- 明确区分读 / 写
- 存在写饥饿与调度复杂性
5.3 StampedLock:乐观并发的引入
- 核心思想:**先假设没有写冲突**
- 失败再回退为悲观锁
这是从“锁竞争”向“冲突检测”的范式迁移。
六、协作而非竞争:同步器模型
6.1 CountDownLatch —— 一次性门闩
模型:事件完成计数
特征:
- 不可重置
- 等待“结果”而非“资源”
6.2 CyclicBarrier —— 阶段性对齐
- 模型:**阶段同步点**
- 可复用
- 适用于迭代式并行计算
6.3 两者的本质区别
| 维度 | CountDownLatch | CyclicBarrier |
|---|---|---|
| 关注点 | 完成 | 对齐 |
| 是否可复用 | 否 | 是 |
| 思维模型 | 门闩 | 栅栏 |
七、资源限流:Semaphore
7.1 抽象模型
- **计数型共享资源控制器**
- 本质不是锁,而是**配额**
7.2 工程意义
- 防止资源被打爆
- 将系统不稳定性转化为排队等待
八、线程间数据交换与通信
8.1 Exchanger
- 双方同步点
- 用于流水线、分治并行
8.2 LockSupport
- park / unpark 是 JVM 层的线程调度原语
- AQS 的基础设施
九、上下文管理:ThreadLocal 及其演进
9.1 ThreadLocal 的本质
线程私有上下文容器
解决的是:
并发环境下的隐式参数传递问题
9.2 核心风险
- 线程池复用 → 脏数据
- 生命周期不一致 → 内存泄漏
9.3 InheritableThreadLocal 的局限
- 只在**线程创建时复制**
- 无法适配线程池
9.4 TransmittableThreadLocal(TTL)
- 本质:**上下文快照 + 回放机制**
- 是对 ThreadLocal 在现代并发模型下的修正
十、工具选型的稳定方法论
| 并发问题 | 首选工具 | 原因 |
|---|---|---|
| 简单互斥 | synchronized | 简单、安全 |
| 高并发互斥 | ReentrantLock | 可控策略 |
| 读多写少 | StampedLock | 乐观并发 |
| 任务协作 | CountDownLatch | 一次性同步 |
| 阶段并行 | CyclicBarrier | 可复用 |
| 资源保护 | Semaphore | 配额控制 |
| 上下文传递 | TTL | 线程池友好 |
关联内容(自动生成)
- [/编程语言/JAVA/JAVA并发编程/基础概念.html](/编程语言/JAVA/JAVA并发编程/基础概念.html) 涵盖原子性、可见性和有序性等基本概念,这些是所有并发工具的基础理论
- [/编程语言/JAVA/JAVA并发编程/线程.html](/编程语言/JAVA/JAVA并发编程/线程.html) 详细介绍了线程模型,这是所有并发工具协调的基础
- [/编程语言/JAVA/JAVA并发编程/线程池.html](/编程语言/JAVA/JAVA并发编程/线程池.html) 讨论了线程池,其中大量使用了诸如CountDownLatch和Semaphore等并发工具
- [/编程语言/JAVA/JAVA并发编程/并发集合.html](/编程语言/JAVA/JAVA并发编程/并发集合.html) 涵盖并发集合,这些集合通常与并发工具类协同工作
- [/编程语言/JAVA/JAVA并发编程/JAVA并发编程.html](/编程语言/JAVA/JAVA并发编程/JAVA并发编程.html) 提供Java并发编程的整体框架,展示了并发工具在整个并发编程体系中的位置