Java的内存模型
物理机器上的内存访问
对于频繁访问的数据,我们总是习惯把它们放到内存缓存中
但是CPU的运算速度比起内存的访问速度还要快几个量级,为了平衡这个差距,于是就专门为CPU引入了高速缓存,频繁使用的数据放到高速缓存当中
每个CPU都拥有自己的高速缓存,内存又是所有CPU共享的公共资源,于是内存此时就成了一个临界区,如果控制不好各个CPU对内存的并发访问,那么就会产生错误,出现数据不一致的情
Java内存模型
Java内存模型与物理机器上内存的访问具有可比性
Java内存模型有一套自己的同步协议来屏蔽掉各种底层硬件和操作系统的不同,实现了跨平台
对于Java来说开发者并不需要关心任何硬件细节,多核CPU和高速缓存在JVM中对应的是Java语言内置的线程和每个线程所拥有的独立栈空间
主内存与工作内存
- 新变量只能在主内存诞生
- 不允许工作内存直接使用未被初始化的变量(意思是在对变量实施use,store前,必须先assign和Load)
主内存
- 所有的变量都存储在主内存中(不包括局部变量与方法参数;局部变量如果是reference,它自身存储在线程私有的内存中,但是它指向的内容存在堆中)
- 变量:实例字段、静态字段、构成数组的元素
工作内存
每条线程有自己的工作内存,保存主内存的副本拷贝
线程对变量的所有操作(赋值、读取等)都在工作内存中进行,不能直接对主内存进行操作
原子操作
一共有8个操作:
原子操作 | 意义 | 操作地 | 备注 |
---|---|---|---|
lock | 锁定变量,为一个线程独占 | 主 | |
unlock | 解除锁定 | 主 | |
read | 主内存的变量值读到工作内存中 | 主 | |
load | read后,将值保存在工作内存副本中 | 工作 | 与read成对出现 |
use | 变量值传递给线程代码执行引擎 | 工作 | |
assigh | 执行引擎处理返回的值重新复制给变量副本 | 工作 | |
store | 变量副本的值存储到主内存中 | 工作 | |
write | store后,将值写入到主内存共享变量中 | 主 | 与store成对出现 |
- 变量在同一时刻只允许一个线程对其进行lock,有多少次lock操作,就必须有多少次unlock操作。在lock操作之后会清空此变量在工作内存中原先的副本,需要再次从主内存read-load新的值。在执行unlock操作前,需要把改变的副本同步回主存