《Java 并发编程·线程与内存模型》目录与学习路径

《Java 并发编程·线程与内存模型》全书导航:说明卷一在三卷本中的位置、四个部分与十五章的依赖关系,给出顺序通读、症状驱动、源码对照三条学习路径,并按部分列出 45 节完整索引、章间依赖、全书实验清单与六个常见误区,便于按症状跳读或按章顺序通读。

这本书的结构

卷一有 50 篇:序、前言、目录 3 篇,正文 15 章 45 节,附录 A/B 2 篇。

正文按能力递进分四个部分:

部分章主题读完解决什么
一1–3线程与可见性知道线程是什么、竞态从哪来、JMM 保证什么
二4–9同步原语与锁会用并能选 synchronized、原子类、显式锁
三10–13执行器与异步编排会配线程池、会用 ForkJoin 和 CompletableFuture
四14–15轻量线程与结构化并发理解虚拟线程与结构化并发的边界

四个部分不是四个独立专题。第一部分是规则,第二部分是规则的最小应用,第三部分是规则的工程化,第四部分是 JDK 25 对前三部分前提的改写。跳过第一部分直接读第三部分,线程池的七个参数会变成死记硬背。

每一节的组织方式

45 节编号文章的结构基本一致,知道这个结构可以用它来快速判断一节要不要细读:

小节写什么怎么用
承接的问题这一节要解决的具体症状或疑问判断是不是你要找的
核心机制2–4 个 ##,讲清语义、实现或取舍主要阅读部分
在 libraryd-conc 里落地完整可编译的类或方法照着改一行再跑
常见错误与边界什么时候不要用、容易错在哪评审时对照
小结三到五条结论复习用
阅读导航上一节 / 下一节顺序读时跳转

不是每节都严格按这六段写,个别节会把「常见错误」合并进「核心机制」。但只要看到「在 libraryd-conc 里落地」,就知道后面有能跑的代码。

三条学习路径

路径 A:顺序通读

适合并发基础不牢、想一次建立完整框架的读者。按 1.1 到 15.3 顺序读,不跳章。

阶段章节时间预算检查点
建立规则第 1–4 章8–10 小时能解释 volatile 保证了什么、没保证什么
掌握原语第 5–9 章10–12 小时能写出正确的有界缓冲区、能选锁
工程化第 10–13 章8–10 小时能配一个不堆积的线程池
新模型第 14–15 章5–6 小时能说清虚拟线程什么时候不适用

时间预算按「读一节、跑一次代码」估算,只读不跑会快很多,但效果差很多。

路径 B:症状驱动

适合带着线上问题来的读者。按症状找章节,不必按顺序:

症状先读再读
库存/余额偶发为负2.1、8.19.1、卷三第 9 章
循环停不下来、标志位不生效3.1、4.13.2、卷三第 9 章
压测 QPS 上不去,CPU 不高9.1、9.210.1、卷三第 3 章
线程池队列堆积、内存上涨10.1、10.210.3、卷三第 10 章
ThreadLocal 串值7.1、7.27.3
定时任务延迟、漏执行11.1、11.312.3
异步任务丢失异常13.213.3
虚拟线程没有变快14.1、14.214.3、卷三第 6 章

症状驱动的读法容易漏掉前置规则。读到第 4 章发现看不懂 happens-before,回到第 3 章补。

路径 C:源码对照

适合准备读 JUC 源码、或正在做技术选型的读者。先读卷一的用法和边界,再读卷二同一主题的实现:

卷一卷二对照点
第 8 章 原子类8.1–8.3CAS 路径、LongAdder 分片
第 9 章 锁选型1.1–3.3AQS、ReentrantLock、读写锁
第 10 章 线程池11.1–11.3ctl、Worker、DelayedWorkQueue
第 12 章 ForkJoin12.1–12.3工作窃取队列
第 13 章 CompletableFuture13.1–13.3依赖栈与触发链

对照读的好处是知道「为什么这样设计」,坏处是容易陷进源码细节。建议先读卷一,把边界记住,再进卷二。

分部分章节

第一部分:线程与可见性(第 1–3 章)

节标题核心问题
1.1从进程到线程:JVM 线程模型Java 线程和内核线程是什么关系,创建要付多少代价
1.2Thread、Runnable、Callable 与任务抽象任务和执行怎么分离,异常去哪了
1.3生命周期、优先级与守护线程六种状态何时出现,daemon 有什么用
2.1竞态的三种形态check-then-act、read-modify-write、发布逸出
2.2线程安全的四类策略不可变、互斥、封闭、并发容器怎么选
2.3用 JCStress 复现计数器竞态怎么让不可见的竞态稳定出现
3.1重排序、可见性与有序性编译器、CPU、缓存各自做了什么
3.2happens-before 八条规则怎么用规则推导而不是背结论
3.3final 字段与安全发布对象为什么会「发布到一半」

第二部分:同步原语与锁(第 4–9 章)

节标题核心问题
4.1volatile 的语义与边界可见性、有序性,以及为什么不保证原子性
4.2synchronized 的字节码与对象头monitorenter 与 ACC_SYNCHRONIZED 的区别
4.3锁消除、锁粗化与偏向锁的移除JIT 会怎么改你的锁
5.1wait/notify 的正确姿势为什么必须在同步块里调用
5.2虚假唤醒与条件谓词循环为什么用 while 不用 if
5.3手写有界缓冲区两个条件队列怎么配合
6.1interrupt 的真实语义标志位、异常、清除与恢复
6.2两阶段终止与协作式取消怎么让线程安全地停下来
6.3shutdown hook 与释放顺序JVM 退出时谁先谁后
7.1ThreadLocal 的实现与内存泄漏弱引用 key 为什么仍会泄漏
7.2InheritableThreadLocal 与线程池断裂上下文为什么传不进池里
7.3ScopedValue:JDK 25 的作用域值不可变绑定怎么替代 ThreadLocal
8.1CAS 原理与 ABA无锁为什么仍会出错
8.2原子类家族与字段更新器什么时候用哪种原子类
8.3LongAdder 与高竞争累加分片为什么快,什么时候不快
9.1自旋、阻塞与 park/unpark等待的代价在哪里
9.2ReentrantLock 与 synchronized 的取舍什么时候值得换显式锁
9.3读写锁与 StampedLock读多写少真的更快吗

第三部分:执行器与异步编排(第 10–13 章)

节标题核心问题
10.1线程池七参数与执行流程任务什么时候进队列、什么时候开新线程
10.2队列与拒绝策略无界队列为什么危险
10.3监控、动态调参与关闭怎么知道池子快满了
11.1Timer 的缺陷与 ScheduledThreadPoolExecutor一个异常为什么让整个调度停摆
11.2延迟队列与时间轮大量定时任务怎么组织
11.3调度漂移、幂等与补偿fixedRate 和 fixedDelay 差在哪
12.1工作窃取与 ForkJoinPool为什么分治任务要用它
12.2并行流的边界与 commonPool 陷阱parallelStream 什么时候帮倒忙
12.3分治拆分、阈值与异常拆多细才划算
13.1CompletableFuture 的创建与组合扇出聚合怎么写才不丢异常
13.2异常、超时与取消超时后任务真的停了吗
13.3上下文传递与线程池隔离异步链路上的 ThreadLocal 去哪了

第四部分:轻量线程与结构化并发(第 14–15 章)

节标题核心问题
14.1虚拟线程的调度模型十万线程为什么只要几十 MB
14.2pinning:JDK 25 还剩什么synchronized 还会不会钉住载体线程
14.3虚拟线程下的池、ThreadLocal 与限流线程便宜了,什么还贵
15.1StructuredTaskScope 的作用域子任务和父任务怎么绑定生命周期
15.2Joiner、失败传播与取消一个失败怎么取消其余
15.3从 ExecutorService 迁移的边界哪些代码不该迁

前置与附录

篇内容
序三个能力层次、三卷分工、超卖事故
前言环境、目录、依赖、JCStress 配置、preview 开关
附录 A并发 API 速查
附录 B诊断命令与 JFR 事件

章间依赖

章依赖原因
21先知道线程怎么创建,再谈多个线程的竞态
32竞态是现象,JMM 解释原因
43volatile 和 synchronized 的语义由 happens-before 定义
5–64等待通知和中断都建立在监视器语义上
72、4线程封闭与内存泄漏要先理解可见性
83、4CAS 的内存语义与 volatile 同源
95、8显式锁是监视器与 CAS 的组合
10–116、9线程池的关闭依赖中断,队列依赖锁
12–1310都建立在执行器抽象上
143、7、10虚拟线程改写的是线程成本与上下文传递
1514结构化并发管理的是虚拟线程的生命周期

这张表可以反过来用:读到某一章卡住,先确认它依赖的章节是否读懂。

全书实验清单

下面这些实验在对应章节里都有完整代码。想先建立直觉,可以挑前三个跑一遍:

实验章节手段能看到什么
丢失更新2.3JCStress LostUpdate约四成样本只生效一次自增
CAS 对照2.3JCStress AtomicCounter丢失更新为 0
可见性丢失3.1普通 Java 程序去掉 volatile 后循环不退出
字节码4.2javap -c / javap -vmonitorenter 与 ACC_SYNCHRONIZED
偏向锁移除4.3JVM 参数Unrecognized VM option 'UseBiasedLocking'
有界缓冲区5.3JUnit + 多线程条件队列的等待与唤醒
ThreadLocal 泄漏7.1线程池 + 弱引用观察不 remove 时 value 不释放
原子类对比8.3JMH8 线程下 LongAdder 快约一个量级
线程池观测10.1jcmd / JFR池大小、活跃数、队列长度
虚拟线程规模14.110 万线程探针创建并 join 约百毫秒级,堆峰值几十 MB
pinning14.2JFR jdk.VirtualThreadPinnedJDK 25 下 synchronized 不再产生事件
结构化并发取消15.2preview 程序一个子任务失败,其余被取消

实验的绝对值依赖机器,书里只承诺相对关系和现象。比如 LongAdder 的倍数在 4 核和 10 核机器上不同,但「高竞争下明显快于 AtomicLong」这个方向是稳定的。

六个常见误区

读之前先排除这几个误解,能少走很多弯路:

误区一:volatile 保证原子性。 它只保证可见性和有序性。volatile int x; x++ 仍然是读、加、写三步,并发下照样丢失更新。

误区二:synchronized 一定慢。 低竞争时它经过 JIT 优化后可能比 ReentrantLock 更快。慢的是高竞争下的阻塞与唤醒,不是关键字本身。

误区三:线程池越大吞吐越高。 线程数超过 CPU 或下游承载能力后,上下文切换和排队会让吞吐下降。池的大小由任务类型和目标时延决定,不由「越多越好」决定。

误区四:LongAdder 可以替代 AtomicLong。 需要精确读取当前值、compareAndSet、或者把计数当作状态判断时,LongAdder 不合适。它的 sum() 只是弱一致的快照。

误区五:虚拟线程可以无限创建。 虚拟线程便宜,但它访问的数据库连接池、HTTP 客户端连接、文件句柄仍然有限。把十万虚拟线程直接打到十个连接上,只会把等待挪个位置。

误区六:用并发容器就线程安全了。 ConcurrentHashMap 保证单次操作安全,不保证「先 get 再 put」这组操作的原子性。复合操作要么用 compute,要么自己加锁。

阅读时容易卡住的地方

卡点原因怎么办
happens-before 太抽象缺少具体交错先看 3.1 的停机标志例子,再看 3.2 的规则
提前遇到 AQS那是卷二内容卷一只需要知道 Lock 接口和行为
preview 代码编译失败缺 --enable-preview回前言看编译与运行参数
JCStress 启动 NPE缺注解处理器配置回前言看 annotationProcessorPaths
JMH 数字波动大状态作用域或迭代次数不对看 8.3 的 Scope.Benchmark 示例

与三卷本的关系

  • 卷二《JUC 源码与容器》只讲卷一用到的类的内部实现,不重复用法。
  • 卷三《性能诊断与事故》只讲卷一的规则在线上如何失效、如何定位,不重复规则本身。
  • 三卷共享 libraryd-conc,但每卷可以独立阅读。只读卷一不会因为没读卷二而看不懂。

版本与实验口径

  • 所有代码以 JDK 25 编译,--release 25。
  • StructuredTaskScope 是 preview,使用时编译和运行都要加 --enable-preview;ScopedValue 已转正,不需要任何 preview 参数。
  • JCStress 0.16、JMH 1.37 的版本固定,不跟随快照。
  • 「本机输出」来自 Apple M1 Pro、10 核、32 GB、macOS 26.3。换机器绝对值会变。
  • 未实跑的容量数字、性能预期会标注「按实现推导」或「示例值」。

读完本书之后

如果你按顺序读完了卷一,应该能做到:

  • 拿到一段并发代码,能指出它依赖了哪个 happens-before 规则,或者缺了哪条。
  • 能判断一个场景该用不可变对象、监视器、原子类还是并发容器,并说清代价。
  • 能配一个带边界、能监控、能优雅关闭的线程池。
  • 能解释虚拟线程为什么快、在什么情况下不快。

这些能力不保证你能通过所有面试,但能保证你在代码评审时看出「这里少了一把锁」和「这里多了一把锁」。前者是正确性问题,后者是性能问题,两者都值得指出来。

想继续深入,读卷二;想把规则放到故障现场检验,读卷三。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《Java 消息中间件·事件驱动架构》附录 B 架构决策记录模板
  2. 《Java 消息中间件·事件驱动架构》附录 A 术语表
  3. 《Java 消息中间件·事件驱动架构》15.3 全书验收