并发编程(Concurrent Programming)¶
并发编程是 Java 开发的核心技能之一,它让程序能够同时处理多个任务,充分利用多核 CPU 资源,提升系统吞吐量和响应速度。然而,并发也带来了线程安全、内存可见性、死锁等复杂问题,需要深入理解底层机制才能写出正确高效的并发代码。
1. 发展历程与技术演进¶
timeline
title Java 并发编程发展历程
section JDK 1.0-1.4
1996-2004 : 基础线程模型
: Thread/Runnable/synchronized
: wait/notify 基本同步
section JDK 5.0 革命
2004 : java.util.concurrent (JUC)
: Atomic*/Lock/Condition
: Executor 线程池框架
: ConcurrentHashMap
section JDK 6-8 优化
2006-2014 : synchronized 锁升级优化
: Fork/Join 框架
: CompletableFuture 异步编程
section JDK 9+ 现代并发
2017+ : Reactive Streams
: 虚拟线程 (Project Loom)
: 向量化 API (Project Panama) 2. 并发编程全景图¶
flowchart TB
subgraph "并发编程三大支柱"
A["<b>基础机制</b><br>JMM / 线程模型 / 同步原语"]
B["<b>并发工具</b><br>Lock / AQS / 线程池 / 工具类"]
C["<b>并发集合</b><br>ConcurrentHashMap / CopyOnWrite / 阻塞队列"]
end
subgraph "底层支撑"
D["CPU 多核架构"]
E["内存模型 (JMM)"]
F["指令重排与内存屏障"]
end
subgraph "高级特性"
G["异步编程 (CompletableFuture)"]
H["并行计算 (Fork/Join)"]
I["响应式编程 (Reactive Streams)"]
end
subgraph "实战场景"
J["高并发服务"]
K["数据处理流水线"]
L["缓存与消息队列"]
end
D --> A
E --> A
F --> A
A --> B
A --> C
B --> G
B --> H
C --> J
C --> K
G --> I
H --> L 3. 知识地图¶
mindmap
root((并发编程))
基础理论
JMM(Java 内存模型)
happens-before 规则
内存可见性
指令重排序
CPU 多核架构
缓存一致性 MESI
内存屏障
线程基础
生命周期与状态
中断机制
同步机制
synchronized
锁升级机制
Monitor 原理
volatile
内存屏障
happens-before
CAS 与原子类
ABA 问题
Atomic*/LongAdder
并发工具 JUC
Lock 框架
ReentrantLock
ReadWriteLock
AQS AbstractQueuedSynchronizer
CLH 队列
状态管理
并发工具类
CountDownLatch
CyclicBarrier
Semaphore
线程池
ThreadPoolExecutor
参数配置与调优
并发集合
ConcurrentHashMap
JDK 7 vs JDK 8
size 方法实现
CopyOnWrite 系列
CopyOnWriteArrayList
CopyOnWriteArraySet
阻塞队列
ArrayBlockingQueue
LinkedBlockingQueue
PriorityBlockingQueue
高级主题
异步编程
CompletableFuture
FutureTask
并行计算
Fork/Join 框架
Parallel Stream
内存模型深入
final 内存语义
ThreadLocal 原理
实战陷阱
死锁与活锁
检测与预防
资源竞争
锁粒度优化
性能调优
锁消除/锁粗化
逃逸分析 4. 知识点导航表¶
| # | 知识点 | 核心一句话 | 详细文档 |
|---|---|---|---|
| 1 | JMM 与内存模型 | Java 对硬件内存模型的抽象,通过 happens-before 保证可见性有序性 | 并发基础:JMM 与线程同步 |
| 2 | synchronized | JDK 内置锁,支持锁升级(无锁→轻量级→重量级),JDK 15+ 默认禁用偏向锁 | 并发基础:JMM 与线程同步 §4 |
| 3 | volatile | 通过内存屏障保证可见性有序性,不保证原子性,解决指令重排问题 | 并发基础:JMM 与线程同步 §5 |
| 4 | CAS 与原子类 | 无锁原子操作,基于 CPU 硬件指令,ABA 问题用 AtomicStampedReference 解决 | 并发基础:JMM 与线程同步 §6 |
| 5 | Lock 与 AQS | 比 synchronized 更灵活的锁机制,支持可中断、超时、公平锁等特性 | 并发工具:Lock、AQS 与线程池 §7-8 |
| 6 | 线程池 | 复用线程资源,避免频繁创建销毁开销,核心参数决定吞吐量与资源消耗 | 并发工具:Lock、AQS 与线程池 §9 |
| 7 | 并发工具类 | CountDownLatch 一次性等待,CyclicBarrier 可重复屏障,Semaphore 限流 | 并发工具:Lock、AQS 与线程池 §8 |
| 8 | ConcurrentHashMap | 分段锁(JDK7)→ CAS + synchronized(JDK8),高并发下性能优异 | 并发集合与实战陷阱 §11 |
| 9 | 死锁与活锁 | 死锁:四个必要条件;活锁:线程不断重试但无法前进;饥饿:长期得不到资源 | 并发集合与实战陷阱 §12 |
| 10 | 异步编程 | CompletableFuture 提供链式异步编程,支持组合、异常处理等高级特性 | 后续专题(规划中) |
5. 高频问题索引表¶
| 问题 | 详见 |
|---|---|
| synchronized 和 ReentrantLock 有什么区别? | 并发工具:Lock、AQS 与线程池 §7.1 |
| volatile 能保证原子性吗?为什么? | 并发基础:JMM 与线程同步 §5.3 |
| 什么是 ABA 问题?如何解决? | 并发基础:JMM 与线程同步 §6.2 |
| 线程池的核心参数如何配置? | 并发工具:Lock、AQS 与线程池 §9.3 |
| ConcurrentHashMap 在 JDK7 和 JDK8 的实现有何不同? | 并发集合与实战陷阱 §11.1 |
| 什么是死锁?如何检测和避免? | 并发集合与实战陷阱 §12.1 |
| ThreadLocal 的内存泄漏问题如何解决? | 并发工具:Lock、AQS 与线程池 §10.2 |
| 什么是 happens-before 规则? | 并发基础:JMM 与线程同步 §2.2 |
| synchronized 的锁升级过程是怎样的? | 并发基础:JMM 与线程同步 §4.2 |
| CountDownLatch 和 CyclicBarrier 有什么区别? | 并发工具:Lock、AQS 与线程池 §8.1-8.2 |
6. 学习路径建议¶
🚀 初学者路径(建议顺序)¶
- 先掌握基础:线程生命周期、synchronized、volatile 的基本用法
- 理解底层机制:JMM 内存模型、happens-before 规则、锁升级原理
- 学习 JUC 工具:Lock、线程池、并发工具类的使用场景
- 实战练习:ConcurrentHashMap、死锁检测与避免
- 深入优化:性能调优、异步编程、高级并发模式
💡 实践建议¶
- 从 synchronized 开始:大多数场景下 synchronized 性能足够且更安全
- 谨慎使用 volatile:只用于状态标志位,不用于计数等需要原子性的场景
- 善用线程池:避免手动创建线程,使用合适的拒绝策略
- 注意资源清理:ThreadLocal 使用后及时 remove,线程池及时 shutdown
⚠️ 常见陷阱¶
- 锁粒度不当:锁太粗影响性能,锁太细可能死锁
- 误用 volatile:以为能保证原子性,实际只能保证可见性
- 线程池参数配置错误:核心线程数、队列大小设置不合理导致性能问题
- 死锁忽视:多个锁的获取顺序不一致可能导致死锁
📖 下一步学习:根据你的当前水平和需求,选择对应的专题深入:
- 刚入门 → 从 并发基础:JMM 与线程同步 开始,打好理论基础
- 已有基础 → 直接学习 并发工具:Lock、AQS 与线程池 掌握实战工具
- 面临具体问题 → 查看 并发集合与实战陷阱 解决实际工程难题