来自颜群老师的JVM课程
JMM
用于定义(所有线程的共享变量,不能是局部变量)变量的访问规则
JMM将内存划分为两个区:主内存区、工作内存区
1. 主内存区
真实存放变量。
一般情况下线程都将主内存的数据copy到自己的工作内存中,不直接访问主内存区
2. 工作内存区
主内存中变量的副本,供各个线程使用。
每个线程独占一个工作内存,不能串用。
线程A如何获取线程B的值
- 线程B将数据同步到主内存,操作名:save
- 线程A从主内存中获取最新数据,操作名:load
深入理解线程之间数据交互的原理
- Lock: 线程A独占主内存
- Read: 主内存中的变量copy到线程A的工作内存中
- Load: 将工作内存中的数据赋值到变量副本中
注意:这里和第二步相似,第二步相当于坐车回到村子,但是第三步是从村子回到家。 - Use: 将变量副本传递给线程使用
- Assign: 把线程正在使用的变量,传递给工作内存中的变量副本中
- Store: 将工作内存中变量副本的值,传递到主内存中
- Write: 将传来的变量副本值作为一个主内存中的变量存储
原理和第2、3步类似 - Unlock: 接触线程的独占状态
JVM数据传输会出现的问题
JVM要求以上8个操作必须是原子性的(要么都成功,要么都失败)
但是对于64位的数据类型(long double)有些非原子性协议
可能出现的问题:
在执行以上8个操作时,可能会出现只读取(写入等)了半个long/double数据,因此出现错误
如何避免这个问题:
- 商用JVM已经充分考虑了此问题,无需我们操作
- 可以通过volatile来避免此类问题(读取半个数据的问题)
volatile double d = 10.00;