Java volatile 与 happens-before:可见性、有序性和原子性边界
基线:Java 17+。本文讨论 Java Memory Model,不依赖某个 CPU 架构。
1. volatile 保证什么
对 volatile 变量的写,与之后另一个线程对同一变量的读建立 happens-before 关系。它提供可见性和一定有序性,但不把一组操作变成原子操作。
volatile boolean stopped 可用于发布停止标志。volatile int count 不能安全支持 count++,因为自增包含读取、加一和写回三个动作。
2. 选择正确工具
单变量原子更新使用 AtomicInteger、AtomicReference;复合状态转移使用锁、并发容器或 CAS 循环;发布不可变配置可以使用 volatile 引用;只有在需要底层内存序时才考虑 VarHandle。
3. happens-before 来源
线程启动、线程结束、锁释放与获取、Future 完成以及并发容器的规定操作也能建立可见性关系。不要用“禁止指令重排”替代 JMM 规则。
4. 验证
复杂内存序使用 jcstress,性能对比使用 JMH,业务状态写包含竞争和失败注入的并发测试。volatile 不是锁,也不是复合操作的原子性保证。