Java内存模型(Java Memory Model,JMM)涉及JVM主内存(Main Memory)和线程本地内存(Thread Local Memory)或者称线程工作内存。
JMM用来屏蔽Java程序在不同的硬件和操作系统上访问内存的差异,定义Java程序中变量的访问规则。
JVM的堆内存在主内存中。方法区在持久代实践时在主内存中;在元空间实践时不在主内存中,在直接内存或者称堆外内存中,被操作系统直接管理。
JVM的栈或者称虚拟机栈、本地方法栈、程序计数器是线程私有的,对应内存在线程工作内存中。
主内存中存放类变量本体,线程工作内存可以存放类变量副本。类变量副本之间不直接交互,必须通过类变量本体作中介。
方法局部变量只存在于线程工作内存。
8个有关主内存中的变量、线程工作内存中的变量的操作:
(1)lock(锁定):主内存中的变量被线程锁定。
(2)unlock(解锁):主内存中的变量不再被线程锁定。
(3)read(读取):主内存中的变量的值进入线程工作内存。
(4)load(载入):进入线程工作内存的值给到线程工作内存中的变量。
(5)use(使用):操作逻辑使用线程工作内存中的变量的值。
(6)assign(赋值):操作逻辑的结果值给到线程工作内存中的变量。
(7)store(存储):作线程的工作内存中的变量的值进入主内存。
(8)write(写入):进入主内存的值给到主内存中的变量。
这8个操作遵守的规则:
(1)read和load不允许单独使用。
(2)store和write不允许单独使用。
(3)assign后必须store和write。
(4)没有经过load,不允许use。
(5)没有经过assign,不允许store。
(6)lock后必须重新load。
(7)没有经过lock,不允许unlock。
(8)没有经过store和write,不允许unlock。
Java内存模型围绕并发中的原子性、可见性和有序性设计。
线程安全包括原子性、可见性、有序性。
原子性指数据操作操作不可分割。
可见性指数据操作结果被其他线程感知。
有序性指数据操作按序发生。
volatile自己的规则((1)、(2)保证可见性,(3)保证有序性):
(1)load和use不允许单独使用。
(2)assign和store不允许单独使用。
(3)假定动作A是线程T对变量V实施的use或assign动作,动作F是和动作A相关联的load或store动作,动作P是和动作F相对应的对变量V的read或write动作;类似的,假定动作B是线程T对变量W实施的use或assign动作,动作G是和动作B相关联的load或store动作,动作Q是和动作G相对应的对变量W的read或write动作。如果动作A先于B,那么P先于Q。
先行发生原则:
A操作先行发生于B操作:A操作中对B操作有影响的结果能被B操作感知。
JMM中的先行发生原则:
程序次序原则:控制流前的操作先行发生于控制流后的操作。
管程锁定规则:unlock先行发生于之后对同一个锁的lock。
volatile变量规则:volatile变量的写先行发生于之后对这个变量的读。
线程启动规则:Thread对象的start()方法先行发生于Thread的每个动作。
线程终止规则:Thread操作先行发生于线程的终止检测
线程中断规则:Thread的interrupt()方法先行发生于被中断线程的代码检测到中断事件
对象终结规则:对象初始化方法先行发生于finalize方法
传递性:操作A先行发生于操作B,操作B先行发生于操作C,则操作A先行发生于操作C。
参考:
深入理解Java内存模型:https://www.jianshu.com/p/15106e9c4bf3
Java内存模型(JMM)总结:https://zhuanlan.zhihu.com/p/29881777
CPU结构、高速缓存、总线锁、缓存锁、缓存一致性协议、StoreBuffer、指令重排序、内存屏障:https://blog.csdn.net/haoranhaoshi/article/details/108553396