Java内存模型
Java Memory Model
Java
虚拟机规范中定义了Java
内存模型(Java Memory Model,JMM)
,用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java
程序在各种平台下都能达到一致的并发效果。
Java
内存模型规定了所有的变量都存储在主内存中(此处的主内存与介绍物理硬件时提到的主内存名字一样,两者也可以类比,但物理上它仅仅是虚拟机内存的一部分)。每条线程还有自己的工作内存(可与前面讲的处理器高速缓存类比),线程的工作内存中保存该线程使用的变量的主内存副本,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的数据。不同的线程之间也无法直接访问对方工作内存的变量,线程间变量值的传递均需要通过主内存来完成,线程、主内存、工作内存三者的交互关系如图:
这里所讲的主内存、工作内存与Java
内存区域中的Java
堆、栈、方法区等并不是同一个层次的堆内存的划分,这两者基本上是没有任何关系的。如果两者一定要勉强对应起来,那么从变量、主内存、工作内存的定义来看,主内存主要对应于Java
堆中的对象实例数据部分,而工作内存则对应于虚拟机栈中的部分区域。从更基础的层次上说,主内存直接对应于物理硬件内存,而为了获取更好的运行速度,虚拟机(或者是硬件、操作系统本身的优化措施)可能会让工作内存优先存储于寄存器和高速缓存中,因为程序运行时主要访问的是工作内存。
内存间交互操作
关于主内存与工作内存之间具体的交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步回主内存这一类的实现细节,Java
内存模型中定义了以下8种操作来完成。Java
虚拟机实现时必须保证下面提及的每一种操作都是原子的、不可再分的。
lock
(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。unlock
(解锁):作用于主内存的变量,他把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。read
(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load
动作使用。load
(载入):作用于工作内存的变量,它把read
操作从主内存中得到的变量值放入工作内存的变量副本中。use
(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。assign
(赋值):作用于工作内存的变量,它把一个从执行引擎接收的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令是执行这个操作。store
(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write
操作使用。write
(写入):作用于主内存的变量,它把store
操作从工作内存中得到的变量的值放入主内存的变量中。
如果要把一个变量从主内存拷贝到工作内存,那就要按顺序执行read
和load
操作,如果要把变量从工作内存同步回主内存,就要按顺序执行store
和write
操作。注意,Java
内存模型只要求上述两个操作必须按顺序执行,但不要求是连续执行。也就是说read
和load
之间、store
与write
之间是可以插入其他指令的。