java内存分为主内存和工作内存,主内存可以理解为java内存划分中的堆、方法区,工作内存分可理解为程序记数区、本地方法栈、本地虚拟机栈。
java的主内存和工作内存都是虚拟的,和实际的硬件结构并不一致,它们可能存在于CPU中的寄存器、CPU缓存、主内存中,编译器重排序、指令重排序、cpu缓存会导致程序出现不一致的情况,所以需要禁止指令重排、插入屏障等操作
java内存模型可以理解为一些对变量访问方式的规则,以向程序员提供内存可见性保证(禁止指令重排、插入屏障等操作,形成了happend-before原则)
锁语义的happend-before原则: 写锁对读锁可见、传递性
volatile 关键字的happend-before原则:
volatile 关键字能够保证有序性和可见性,但是不保证修改涉及到旧值的原子性(如i++,i+=2等),64位的数据类型(long和double)加volatile修饰的话保证读写原子性(一般虚拟机都选择将64位的数据类型的读写操作实现为原子操作)。 ~多谢震震同学的提醒!
volatile 关键字有两点:1、禁止指令重排序(可理解为有序性的保证,通过插入内存屏障,该内存屏障就是一条CPU指令,禁止对该指令前后的指令进行重排序);2、保证内存可见性(强制刷新CPU缓存)
happens-before原则辅助保证原子性、可见性、有序性。