Programming Concurrency on the JVM: Mastering Synchronization, STM, and Actors
作者: Venkat Subramaniam
语言: 英文
出版年份: 2011
下载链接:
书籍均收集自互联网,仅供学习和研究使用,请莫用于商业用途。谢谢合作。

书籍摘要

一、书籍定位与主旨

Venkat Subramaniam 在《Programming Concurrency on the JVM》中提出: “并发不是语法糖,而是思维方式。”
全书围绕“如何在 JVM 上安全、高效、可维护地做并发”展开,给出三条主线:

  1. 现代 JDK 并发工具(java.util.concurrent)
  2. 软件事务内存(STM)
  3. 演员模型(Actor)

作者强调:共享可变状态是万恶之源;隔离可变或不可变才是正道。书中用大量可运行示例(Java / Scala / Groovy / JRuby / Clojure)演示三种模型如何落地,并对比性能、可读性、调试成本。

二、内容分层速览

Part I 策略与思维(第1-3章)

  • 并发价值:榨干多核、降低延迟、提升吞吐
  • 并发陷阱:可见性、竞态、死锁、饥饿
  • 设计取舍:共享可变 vs 隔离可变 vs 纯不可变
  • 分治公式:线程数 ≈ CPU核 / (1 – 阻塞系数)
  • 负载划分:IO 密集用“超多线程”,计算密集用“核数线程”+“超多任务片”

Part II 现代 JDK 并发(第4-5章)

  • ExecutorService、ForkJoinPool、CountDownLatch、CyclicBarrier、CompletableFuture 用法与坑点
  • ConcurrentHashMap、BlockingQueue、CopyOnWriteArrayList 等可扩展集合为何比 synchronized 集合快
  • ReentrantLock、ReadWriteLock、StampedLock 相对 synchronized 的优势:可限时、可中断、可公平、可多条件
  • 共享可变代码重构六步曲:
    1. 禁止构造函数里启动线程
    2. 用线程池代替裸 Thread
    3. 保证跨内存屏障(volatile / synchronized / final)
    4. 缩小锁粒度(字段级、分段锁、原子变量)
    5. 复合操作加锁或 CAS
    6. 用不可变消息传递替代共享可变

Part III 软件事务内存(第6-7章)

  • STM 核心:把“锁”上升为“事务”,让运行时自动处理冲突、重试、可见性
  • Clojure 示范:ref / dosync / alter / commute / ensure;写偏(write skew)与解决办法
  • Akka-STM(基于 Multiverse)在 Java/Scala 中的 API:
    • Atomic<T> + atomically()
    • 嵌套事务、只读事务、阻塞重试 retry()
    • 提交钩子 deferred()、回滚钩子 compensating()
  • STM 适用场景:读多写少、冲突概率低;高冲突写场景会退化为“不断重试”

Part IV 演员模型(第8-9章)

  • Actor = 单线程 + 邮箱 + 不可变消息;多个 Actor 共享线程池,顺序处理邮箱,天然无锁
  • Akka 基础:UntypedActor(Java)/ Actor trait(Scala);!、!!、!!! 三种消息发送语义
  • 案例:多线程统计素数、递归遍历目录大小——Actor 版代码量下降 30-50%,性能持平
  • Typed Actor:接口+实现,方法调用即消息;适合既想保留 OO 语义又要并发安全的场景
  • 内部定时任务(murmurs):用 Scheduler 发消息给自身,避免外部线程碰状态
  • 远程 Actor:Netty + Protobuf,透明跨进程发消息
  • 协调一致性:
    • Transactor(STM + Actor):coordinate() 把多个 Actor 拉进同一事务,成功一起提交,失败一起回滚
    • Coordinating Typed Actor:@Coordinated 注解 + coordinate{…} 代码块,实现跨账户转账原子性

Part V 多语言实战(第9章)

  • Groovy:GPars 提供 DefaultActor / actor{} 闭包;与 Java 互操作无门槛
  • JRuby:直接 import Clojure STM 或 Akka;注意 NativeException 包装需手动 unwrap
  • Scala:既可用 Akka 原生 API,也可直接用 Clojure STM 的 Ref 与 LockingTransaction
  • 结论:并发模型与语言正交;遵循“值不可变、事务幂等、消息不可变”三原则即可

三、特色与价值

  1. 一书三模型:把 JDK、STM、Actor 放在同一坐标系对比,帮助读者根据“冲突概率、吞吐需求、代码复杂度”做选型
  2. 多语言对照:同一示例用 Java/Scala/Groovy/JRuby/Clojure 五种语法实现,方便团队跨语言落地
  3. 性能数据翔实:作者在同一台双核/八核机器跑基准测试,给出线程数-分片数-耗时曲线,避免“拍脑袋”调优
  4. 重构步骤清晰:共享可变代码 → 加锁 → 缩小锁 → 原子变量 → 不可变消息 → Actor/STM,层层递进,老代码改造不再无从下手
  5. 坑点与边界直言不讳:STM 高写冲突会退化为重试风暴;Actor 可能死锁或饿死;远程 Actor 需关注序列化——提前帮读者踩坑

四、适合读者

  • 拥有 1 年以上 JVM 经验,却被“并发 bug 难重现、难调试”折磨的工程师
  • 需要维护老系统 synchronized 代码,想逐步迁移到现代并发模型的架构师
  • 对函数式、不可变、Actor、STM 感兴趣,却苦于“概念懂、落地难”的开发者
  • 技术团队负责人想在 Java/Kotlin/Scala/Groovy 多语言栈中统一并发规范

五、阅读建议

  1. 先通读 Part I 建立“并发思维”,再挑自己最急需的模型深入
  2. 每章示例代码均可直接运行,建议:
    • 把线程数、分片数、超时参数当变量,亲眼看“性能曲线”
    • 故意制造高冲突(多线程写同一 ref / 同一账户),观察 STM 重试、Actor 邮箱堆积
  3. 老项目改造:
    • 第 5 章“共享可变六步曲”当 checklist,逐条对照现有代码
    • 新模块优先用 Actor(隔离可变)或 STM(读多写少),老模块逐步“边缘推进”
  4. 多语言混合:本书示例均可互操作,团队可保留各自语言习惯,又共享同一并发模型

六、总结

《Programming Concurrency on the JVM》用“共享不可变、隔离可变、事务自动重试、演员顺序处理”四大法宝,带你逃离 synchronized 的暗坑,在多核时代写出“快且稳”的 JVM 并发代码。

期待您的支持
捐助本站