Java内存模型Java Memory Model,简称JMM,本身是一种抽象的概念并不真实存在它仅仅描述的是一组约定或规范,通过这组规范定义了程序中(尤其是多线程)各个变量的读写访问方式并决定一个线程对共享变量的写入何时以及如何变成对另一个线程可见,关键技术点都是围绕多线程的原子性、可见性和有序性展开的。
指一个操作是不可中断的,即多线程环境下,操作不能被其他线程干扰。
Java中普通的共享变量不保证可见性,因为数据修改被写入内存的时机是不确定的,多线程并发下很可能出现"脏读"。
每个线程都有自己的工作内存,线程自己的工作内存中保存了该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取,赋值)都必需在线程自己的工作内存中进行,而不能够直接读写主内存中的变量。

对于一个线程的执行代码而言,我们总是习惯性认为代码的执行总是从上到下,有序执行。 但为了提供性能,编译器和处理器通常会对指令序列进行重新排序。
指令重排可以保证串行语义一致,但没有义务保证多线程间的语义也一致,即可能产生"脏读"。
关键字,保证不同线程对这个变量进行操作时的可见性,即变量一旦改变所有线程立即可见,指令禁重排,不能保证原子性。
内存屏障 (Memory Barriers / Fences),是一种屏障指令,它使得CPU或编译器对屏障指令的前和后所发出的内存操作执行一个排序的约束。也叫内存栅栏或栅栏指令。

在每个 volatile 写操作的前⾯插⼊⼀个 StoreStore 屏障
在每个 volatile 写操作的后⾯插⼊⼀个 StoreLoad 屏障
volatile关键字保证可见性,意味着∶
对一个volatile修饰的变量进行读操作的话,总是能够读到这个变量的最新的值,也就是这个变量最后被修改的值
一个线程修改了volatile修饰的变量的值的时候,那么这个变量的新的值,会立即刷新回到主内存中
一个线程去读取 volatile 修饰的变量的值的时候,该变量在工作内存中的数据无效,需要重新到主内存去读取最新的数据