JMM

269 阅读4分钟

JMM:Java Memory Model,Java内存模型

JMM为了避免在不同操作系统,不同硬件下内存访问存在差异带来的各种问题,屏蔽了各种硬件以及操作系统的内存,以实现Java程序在各种平台下达到并发一致的效果。

 JMM规定所有的变量都存储在主存中(包括实例变量,静态变量),但是不包括局部变量和方法参数。线程持有自己的工作内存,线程从主存中拷贝一份变量到自己的工作内存中,在工作内存中对变量进行操作,然后将变量刷新回主存,而不能直接对主存中的变量进行读写操作。这是JMM定义的线程基本工作方式。

**JMM三大特性:****原子性,**可见性,有序性

原子性

原子性是指该操作执行期间不会被其他线程的操作加塞,即原子性。Java代码块中可以使用synchronized关键字来保证代码块的原子性,即锁。

int i=1;  //基本的赋值操作,原子操作 
int j=i;  // 先读取i的值,再赋值给j,两步操作,不能保证原子性
i++;      // 这一步其实可以分为读取i的值,i+1i+1赋值给i,三步操作,不能保证原子性
i=i+1;    // 等价于第三步

可见性

Java提供volatile关键字来保证可见性,线程从主存读取了由volatile修饰的变量,拷贝到自己的工作内存中进行操作,一旦修改,必须将这个改变刷新回主存中,这时候其他线程得知该变量的值已经发生改变,便重新从主存中读取,这就是可见性。

除了volatile之外,final和synchronized也能保证可见性。

有序性

使用volatile来保证有序性,而volatile是通过使用内存屏障来禁止指令重排,这样就保证了有序性。看下面一段代码

int i=1;
int j=2;
volatile int m=3;
int n =4;
int p=5;

在实际的执行代码过程中,并不是顺序来执行的,操作系统为了提高程序的执行效率,在不影响最终结果的情况下,会对指令的执行顺序进行调整,这个过程也叫指令的重排序。相当于i=1,j=2可能并不是按照代码顺序来执行的,有可能是j(p)先赋值,而i(n)后赋值,但是不管i(p),j(n)的赋值顺序如何,i,j的赋值必须在m之前,n,p的赋值必须在m之后。

八种内存交互操作

线程工作内存与主存的操作主要有8个,分别是 lock read  load  use assign store write  unlock。

lock(锁定):锁定主内存中的变量,把变量标识置为线程独有。

read(读取):作用于主内存中的变量,将变量传输到工作内存中。

load(加载):作用于工作内存,将主存的变量读取到工作内存中。

use(使用):作用于工作内存,将变量传输到执行引擎中使用。

assign(赋值):作用于工作内存,从执行引擎中接受值并赋值给变量。

store(存储):作用于工作内存,将工作内存的变量传输到主内存中。

write(写入):作用于主内存,把store操作得到的值写入主内存中。

unlock(解锁):作用于主内存中的变量,释放锁定变量,这样变量才能被其他线程锁定。

其中read,load,store,write不允许单独存在,即read完必须load,store完必须write。

补充一下JMM对8种内存交互操作制定的规则:

  • 不允许read、load、store、write操作之一单独出现,也就是read操作后必须load,store操作后必须write。
  • 不允许线程丢弃他最近的assign操作,即工作内存中的变量数据改变了之后,必须告知主存。
  • 不允许线程将没有assign的数据从工作内存同步到主内存。
  • 一个新的变量必须在主内存中诞生,不允许工作内存直接使用一个未被初始化的变量。就是对变量实施use、store操作之前,必须经过load和assign操作。
  • 一个变量同一时间只能有一个线程对其进行lock操作。多次lock之后,必须执行相同次数unlock才可以解锁。
  • 如果对一个变量进行lock操作,会清空所有工作内存中此变量的值。在执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值。
  • 如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量。
  • 一个线程对一个变量进行unlock操作之前,必须先把此变量同步回主内存。

volatile:不保证原子性,禁止指令重排,可见性

禁止指令重排按顺序又分为编译器指令重排,指令级指令重排,内存指令重排。

valatile禁止指令重排的原理:内存屏障,具体可以了解下Java内存屏障

部分内容参考:

zhuanlan.zhihu.com/p/258393139…