volatile核心作用是保障可见性与禁止指令重排序,不保证原子性;适用于布尔标志等一写多读场景,如private volatile boolean running = true;不可用于i++等复合操作。

Java 中处理多线程并发下的变量可见性问题,核心是打破“线程只读写自己工作内存”的默认行为,强制让修改对其他线程及时可见。这不是靠加 sleep 或打印来“碰巧修复”,而是通过明确的内存语义控制来保障。
用 volatile 修饰状态标志类变量
适用于布尔开关、启动/停止信号等“一写多读”且无复合逻辑的场景。它不保证原子性,但能确保每次读都从主内存取最新值,每次写都立刻刷回主内存,并禁止相关指令重排序。
- 直接在字段声明处加上 volatile,比如
private static volatile boolean running = true; - 避免用于
i++、count += 1这类读-改-写操作——这些仍会因非原子性导致丢失更新 - 注意:volatile 不能替代锁来保护多个变量之间的逻辑关系(例如“先设 flag 再更新 data”,需用 synchronized 保证整体可见+有序)
用 synchronized 或 ReentrantLock 保护临界区
不仅解决可见性,还同时提供原子性和互斥访问。进入同步块前,线程会清空工作内存中对应变量的副本;退出时,把所有修改强制写回主内存。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 即使临界区内只读一个变量,也能看到之前其他线程在同锁下写入的最新值
- 被同一把锁保护的所有共享变量,天然具备可见性保障
- 显式锁(如
ReentrantLock)与 synchronized 具有相同的内存语义,只要成对调用lock()和unlock()
用原子类替代普通基本类型
如 AtomicBoolean、AtomicInteger、AtomicReference 等。它们底层基于 volatile + CAS,既保证变量读写的可见性,又对常见操作(如 getAndIncrement、compareAndSet)提供原子性。
立即学习“Java免费学习笔记(深入)”;
- 适合计数器、状态切换、无锁编程等需要“读-改-写”安全的场景
- 比单纯加锁更轻量,尤其在竞争不激烈时性能更好
- 注意:原子类本身是线程安全的,但多个原子变量之间的协作仍需额外同步
避免常见误区
很多看似“应该可见”的写法其实无效:
- static 不等于可见:静态变量只是类级别共享,不解决缓存一致性
- System.out.println() 不是同步手段:它可能因触发内存屏障而“偶然生效”,但不可靠、不具语义
- final 只保构造安全:仅适用于对象发布阶段的初始化可见性,不适用于运行期反复修改
- 没锁也没 volatile 的普通字段读写,就是可见性裸奔:哪怕在单核机器上测试正常,换到多核或不同 JVM 版本就可能暴露问题

















