主题
并发编程技术栈总览
蒸馏自
B40-资源/语雀-Java开发/多线程与高并发/(26 篇:多线程基础 156KB + Java 中的锁 66KB + 王宝令《Java 并发编程实战》理论基础 13 篇 + JUC 5 篇 + Happens-Before + 逃逸分析)。本页是并发域的全局地图,细节见各概念卡。
一句话机制
并发编程的所有复杂性,都源于可见性、原子性、有序性三大问题;Java 用 JMM(内存模型)规范可见性/有序性,用锁/CAS 解决原子性,再往上封装出 AQS、线程池等工具。 理解并发 = 先吃透「三大问题」,再沿着「JMM → 锁/CAS → AQS → 线程池」逐层往上。
并发全景分层图
| 层 | 解决什么 | 关键机制 | 详情页 |
|---|---|---|---|
| 三大问题 | Bug 的根 | 可见性(缓存)/原子性(切换)/有序性(重排) | 概念卡片:Java内存模型与Happens-Before |
| JMM | 按需禁用缓存/重排 | volatile / synchronized / final + Happens-Before 规则 | 概念卡片:Java内存模型与Happens-Before |
| 锁 / CAS | 原子性 | synchronized 锁升级 / ReentrantLock / CAS 乐观锁 | 概念卡片:synchronized锁升级与Monitor · 概念卡片:CAS乐观锁与原子类 |
| AQS | 锁的通用框架 | state + FIFO 队列 + park/unpark | 概念卡片:AQS同步器框架 |
| 线程池 | 线程复用 | ThreadPoolExecutor 参数 + 执行流程 | 概念卡片:Java线程池ThreadPoolExecutor |
三大问题一句话
| 问题 | 根因 | 典型表现 |
|---|---|---|
| 可见性 | CPU 多级缓存 | 线程 A 改了 flag,线程 B 读不到,死循环 |
| 原子性 | 线程切换打断复合操作 | count++ 两步之间被切换,结果丢失 |
| 有序性 | 编译器/CPU 指令重排 | DCL 单例拿到半初始化对象 |
Happens-Before 不是"时间先后",而是"前一个操作的结果对后一个可见"的保证协议。判断并发安全不靠猜,靠「找两条操作,套 HB 规则能否连通」。
锁与 CAS 的选择
| 维度 | synchronized / ReentrantLock(悲观锁) | CAS(乐观锁) |
|---|---|---|
| 思路 | 先加锁再操作,冲突一定防住 | 先不改,更新时检查有没有被改过 |
| 代价 | 线程阻塞/唤醒/上下文切换 | 失败自旋,占 CPU |
| 适合 | 临界区复杂、多变量、竞争激烈、需等待唤醒 | 简单原子操作、冲突不激烈、想免阻塞 |
| 代表 | 转账、库存扣减+日志、生产者消费者 | 自增计数、状态 0→1、引用替换 |
不变量:volatile 管「看得见最新值」,CAS 管「比较并更新这个动作是原子的」,两者各管一半、常搭配使用。synchronized 全包(可见性+原子性+有序性)。
synchronized 锁升级一句话
synchronized 的锁存在对象头 Mark Word 里,状态从低到高:无锁 → 偏向锁 → 轻量级锁 → 重量级锁,只能升级不能降级。偏向锁(单线程反复加锁,仅 1 次 CAS 换 ThreadID)→ 轻量级锁(有竞争,CAS + 自旋,不阻塞)→ 重量级锁(自旋超限或多线程竞争,基于 OS Mutex,线程阻塞)。
线程池一句话
ThreadPoolExecutor 提交任务三步:① 线程数 < corePoolSize 直接建线程 → ② 否则入队 → ③ 队列满了且 < maximumPoolSize 再建线程,否则走拒绝策略。核心线程靠 queue.take() 阻塞保活,非核心线程靠 queue.poll(keepAliveTime) 超时回收。
常见误解(避坑)
- ❌ "volatile 能保证
count++原子"。→ volatile 只保证可见性,count++是「读-改-写」复合操作,仍会丢更新;要原子得用 CAS(AtomicInteger)或加锁。 - ❌ "锁越多越安全"。→ 锁粒度太小反而引发死锁;「粗粒度锁保护多资源」和「锁粒度太小」是死锁两大来源。
- ❌ "Executor 结尾的类都是线程池"。→
SimpleAsyncTaskExecutor每次新开线程、不是池;Executor接口只是"将来执行命令"的接口,真正代表线程池的是ThreadPoolExecutor。 - ❌ "线程池默认配置就够"。→ 必须手动
new ThreadPoolExecutor(Executors.newFixedThreadPool/newCachedThreadPool用无界队列/无限线程,OOM 风险),且 workQueue 用有界队列。
关联
- 原始资料:✅多线程基础 · Java中的锁(本地锁) · Happens-Before原则 · 02_Java内存模型:看Java如何解决可见性和有序性问题 · CAS详解 · AQS详解 · ✅线程池10个问题
- 概念卡:概念卡片:Java内存模型与Happens-Before · 概念卡片:synchronized锁升级与Monitor · 概念卡片:CAS乐观锁与原子类 · 概念卡片:AQS同步器框架 · 概念卡片:Java线程池ThreadPoolExecutor
- 域地图:A00-百科/Java后端/Java后端