「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」。
Java内存模型(Java Memory Model, JMM )用来屏蔽各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。
主内存与工作内存
- 所有的变量都存储在主内存(Main Memory)中。
- 每条线程有自己的工作内存(Working Memory),线程的工作内存中保存了被该线程使用的变量的主内存副本[2],线程对变量的所有操作(读取、赋值等)都必须在工作内 存中进行,而不能直接读写主内存中的数据。
- 不同的线程之间也无法直接访问对方工作内存中的变 量,线程间变量值的传递均需要通过主内存来完成。
线程、工作内存、主内存的交互关系如下图所示:
从基础的层次上说,主内存直接对应于物理硬件的内存;为了获取更好的运行速度,JVM(或者是硬件、操作系统本身的优化措施)可能会让工作内存优先存储于寄存器和高速缓存中。
[2]有部分读者会对这段描述中的“副本”提出疑问,如“假设线程中访问一个10MB大小的对象,也会把这10MB的内存复制一份出来吗?”,事实上并不会如此,这个对象的引用、对象中某个在线程访问到的字段是有可能被复制的,但不会有虚拟机把整个对象复制一次。
内存间交互操作
关于主内存与工作内存之间具体的交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步回主内存这一类的实现细节,Java内存模型中定义了以下8种操作来完成。Java虚拟机实现时必须保证下面提及的每一种操作都是原子的、不可再分的
- lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
- unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量 才可以被其他线程锁定。
- read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以 便随后的load动作使用。
- load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的 变量副本中。
- use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚 拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
- assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收的值赋给工作内存的变量, 每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
- store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随 后的write操作使用。
- write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的 变量中。