1 Java内存模型(JMM)的意义
Java虚拟机规范中试图定义一种Java内存模型来屏蔽掉各种硬件和操作系统的内存访问差异,规定
线程如何,何时能看到其他线程修改过的共享变量的值
在必要时如何同步地访问共享变量
以实现让Java程序在各种平台下都能达到一致性的内存访问效果。
2 主内存与工作内存
Java内存模型的主要目标是定义各个变量的访问规则
即在虚拟机中将变量存储到内存和从内存中取出变量值这样的底层细节
此处的变量包括了实例域,静态域和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的,不存在竞争
为了获得比较好的执行效率,JMM并没有限制执行引擎使用处理器的特定寄存器或缓存来和主内存进行交互,也没有限制即时编译器调整代码执行顺序这类权限。
JMM规定
所有的变量都存储在主内存(Main Memory)
每条线程有自己的工作内存(Working Memory)
保存了该线程使用到的变量的主内存副本拷贝(线程所访问对象的引用或者对象中某个在线程访问到的字段,不会是整个对象的拷贝!)
线程对变量的所有操作(读,赋值等)都必须在工作内存中进行,不能直接读写主内存中的变量
volatile变量依然有工作内存的拷贝,只是他特殊的操作顺序性规定,看起来如同直接在主内存读写
不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均要通过主内存
JVM模型与JMM不是同一层次的内存划分,基本是没有关系的,硬要对应起来,从变量,内存,工作内存的定义来看
主内存 === Java堆中的对象实例数据部分
工作内存 === 虚拟机栈中的部分区域
从更底层的层次来说
主内存直接对应于物理硬件的内存
为了更好的运行速度,虚拟机(甚至硬件系统的本身的优化措施)可能会让工作内存优先存储于寄存器和高速缓存器中,因为程序运行时主要访问读写的是工作内存
3 内存间同步操作
一个变量如何从主内存拷贝到工作内存,从工作内存同步回主内存的实现细节
JMM定义了以下8种操作来完成,都具备原子性
lock(锁定)
作用于主内存变量,把一个变量标识为一条线程独占的状态
unlock(解锁)
作用于主内存变量,把一个处于锁定状态的变量释放,释放后的变量才可以被其它线程锁定
unlock之前必须将变量值同步回主内存
read(读取)
作用于主内存变量,把一个变量的值从主内存传输到工作内存,以便随后的load
load(载入)
作用于工作内存变量,把read从主内存中得到的变量值放入工作内存的变量副本
use(使用)
作用于工作内存变量,把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到的变量的值得字节码指令时将会执行这个操作
assign(赋值)
作用于工作内存变量,把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作
store(存储)
作用于工作内存变量,把工作内存中一个变量的值传送到主内存,以便随后的write操作使用
write(写入)
作用于主内存变量,把store操作从工作内存中得到的值放入主内存的变量中
把一个变量从主内存复制到工作内存
就要顺序执行read和load
把变量从工作内存同步回主内存
就要顺序地执行store和write操作
JMM只要求上述两个操作必须按序执行,而没有保证连续执行
也就是说read/load之间、store/write之间可以插入其它指令
如对主内存中的变量a,b访问时,一种可能出现的顺序是read a->readb->loadb->load