很多工程师对并发的理解停留在"加个 synchronized、给字段加 volatile 就安全了"的层面,一旦线上出现偶发的数据错乱、死循环或者读到"半个对象",就无从下手。这类问题的根源,几乎都可以追溯到 Java 内存模型(Java Memory Model,JMM)。JMM 不是 JVM 的某个实现细节,而是 Java 语言规范第 17 章明确定义的一套规则:它规定了在什么条件下,一个线程对共享变量的写对另一个线程可见,以及在什么条件下允许编译器与处理器进行指令重排序。
本文不打算复述规范原文,而是从重排序、可见性、原子性三个切入点,把 happens-before 的每一条规则和 volatile / final 的内存语义讲透,并结合真实生产环境的 bug 案例给出排查思路与调优建议。
2022/1/8大约 13 分钟