共享变量在工作内存中是主内存变量值的本地缓存快照,而非独立拷贝对象;线程操作的是该缓存副本,修改后需通过volatile写、synchronized退出等同步机制刷新至主内存,否则其他线程可能读到过期值。

共享变量在工作内存中的副本,不是一份独立的“拷贝对象”,而是对主内存中同一变量值的一份本地缓存快照。
副本的本质是缓存,不是复制对象
Java 中的共享变量(如实例字段、静态字段、数组元素)都存放在主内存(即堆内存)。每个线程在访问这些变量时,并不直接读写主内存,而是先将该变量的当前值加载到自己的工作内存中——这个值就是“副本”。它本质上是 CPU 缓存或寄存器中的一份临时存储,不是新建对象,也不占用额外堆空间。
- 多个线程对同一个 int 类型静态变量 count 的读写,各自操作的是自己工作内存里的 count 值,而非直接操作堆里的那个变量本身
- 副本之间互不影响,直到显式同步(如 volatile 写、synchronized 退出、Lock 释放)触发刷新或重载
- 局部变量、方法参数等栈上数据不属于共享变量,不存在副本概念
副本导致可见性问题的典型过程
当线程 A 修改了共享变量后,若未同步,其工作内存中的副本更新不会自动传播到主内存,其他线程的工作内存也不会自动更新。这就造成“我改了,你没看见”的现象。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 线程 A 执行 count = 5 → 更新自己工作内存中的副本
- 未触发同步机制 → 主内存中的 count 仍为旧值(比如 0)
- 线程 B 读取 count → 加载的是自己工作内存里过期的副本(仍是 0),而非主内存最新值
哪些操作能保证副本与主内存一致
不是所有读写都会立即与主内存交互。JMM 规定了特定动作作为“同步点”,强制副本和主内存对齐:
- volatile 变量的每次读:强制从主内存重新加载最新值
- volatile 变量的每次写:强制把值立即刷回主内存
- synchronized 块退出时:将工作内存中所有共享变量副本刷新到主内存
- Lock.unlock() 或 synchronized 块进入时:清空工作内存并从主内存重载变量
副本的存在是为了性能,不是为了隔离
JMM 设计工作内存,根本目的是适配现代硬件的缓存架构——避免每次读写都访问较慢的主内存。它用抽象模型统一描述 CPU 缓存、写缓冲区、寄存器等优化行为。副本不是 Java 语言层的“深拷贝”或“克隆”,而是一种运行时的内存访问路径约定。
- 没有 synchronized 或 volatile 时,编译器和处理器还可能对涉及副本的操作重排序
- happens-before 关系正是用来约束这种重排序,确保某些操作的结果对其他线程“可见”
- 理解副本,关键在于意识到:线程看到的永远是它自己工作内存里的值,而不是“实时的主内存”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










