首先Java内存模型不是“JVM 的内存模型”;

 

Java线程之间的通信采用的是共享内存模型,这里提到的共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程共享变量的写入何时对另一个线程可见。

从抽象的角度来看,JMM定义了线程主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,线程被CPU执行,每个线程都有一个私有的本地内存(如CPU的高速缓存),本地内存中存储了该线程以读/写共享变量的副本

(重点)本地内存是JMM的一个抽象概念,并不真实存在;它涵盖了缓存写缓冲区寄存器以及其他的硬件和编译器优化。

 

 

Java 内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(比如CPU的高速缓存)。

线程变量所有操作都必须在工作内存中进行,而能直接对主存进行操作,并且每个线程不能访问其他线程的工作内存。

 

(重点)那为什么Java的内存模型规范要这样定义导致出现线程本地内存和主存的值不同步呢?为啥线程要有自己的本地内存?

答案是利用缓存改变执行代码顺序达到程序执行效率优化。

例如下面代码:

int a1 = x;
int a2 = y;
int a3 = x;

可能会被转化为:

int a2 = y;
int a1 = x;
int a3 = x;

或者是:

int a1 = x;
int a2 = y;
int a3 = a1;

这样和最初的代码相比,少读x一次。

 

 

Java 内 存 模 型 的 Volatile 关 键 字 和 原 子 性 、 可 见 性 、 有 序 性 和 happens-before 关系等。

一.Volatile 关键字 https://www.cnblogs.com/theRhyme/p/9396834.html

二.要想并发程序正确地执行,必须要保证原子性可见性以及有序性。 只要有一个没有被保证,就有可能会导致程序运行不正确。

 

happens-before 原则(先行发生原则,有序性):

程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在 后面的操作

锁定规则:一个 unLock 操作先行发生于后面对同一个锁的 lock 操作 

volatile 变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作

传递规则:如果操作 A 先行发生于操作 B,而操作 B 又先行发生于操作 C,则可以 得出操作 A 先行发生于操作 C

线程启动规则:Thread 对象的 start()方法先行发生于此线程的每个一个动作

线程中断规则:对线程 interrupt()方法的调用先行发生于被中断线程的代码检测 到中断事件的发生

线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过 Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行

对象终结规则:一个对象的初始化完成先行发生于他的 finalize()方法的开始。

 

硬件内存架构:https://www.cnblogs.com/theRhyme/p/9600148.html

 

Java内存模型——oracle官网文档: https://docs.oracle.com/javase/specs/jls/se9/html/jls-17.html#jls-17.4