什么是JMM?
Java Memory Model简称JMM,一般是指 JSR-133: Java Memory Model and Thread Specification Revision 规定的 Java 内存模型。
Java虚拟机是一个实现了跨平台的虚拟系统,因此它也有自己的内存模型,即Java内存模型(Java Memory Model),简称JMM。
JMM内存模型定义了共享内存系统中多线程程序读写操作的行为规范,通过这些规则来规范对内存的读写操作,从而保证指令执行的正确性。
为什么需要JMM?
Java 为了保证并发编程中可以满足原子性、可见性及有序性 ,诞生出了一个重要的概念,那就是 Java内存模型 (JMM).
JMM内存模型 定义了共享内存系统中多线程程序读写操作行为的规范 。
JMM通过这些规则来规范对内存的读写操作,从而保证指令执行的正确性, 它解决了 CPU 多级缓存、处理器优化、指令重排等导致的内存访问问题 , 保证了并发场景下的一致性、原子性和有序性 。
JMM的三大特性?
Java内存模型是围绕着并发编程中原子性、可见性、有序性这三个特征来建立的,那我们依次看一下这三个特征:
1.原子性
原子性指一个操作是不可中断的,即使是多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行,i++等操作,需要synchronized关键字约束或lock体系的支持。
2.可见性
可见性指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。
3.有序性
有序性对于一个线程的执行代码而言,我们总是习惯地认为代码的执行时从先往后,依次执行的,这样的理解也不能说完全错误,因为就一个线程而言,确实会这样。
但是在并发时,程序的执行可能就会出现乱序,给人直观的感觉就是:写在前面的代码,会在后面执行。
有序性问题的原因是因为程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。
JMM内存模型组成?
Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。
不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。
- 主内存
主要存储的是Java实例对象,所有线程创建的实例对象都存放在主内存中,不管该实例对象是成员变量还是方法中的本地变量(也称局部变量),当然也包括了共享的类信息、常量、静态变量。由于是共享数据区域,多条线程对同一个变量进行访问可能会发现线程安全问题。 - 工作内存
每条线程都有自己的工作内存(Working Memory,又称本地内存,可与前面介绍的处理器高速缓存类比),线程的工作内存中保存了该线程使用到的变量的主内存中的共享变量的副本拷贝。工作内存是 JMM 的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
主要存储当前方法的所有本地变量信息(工作内存中存储着主内存中的变量副本拷贝),每个线程只能访问自己的工作内存,即线程中的本地变量对其它线程是不可见的,就算是两个线程执行的是同一段代码,它们也会各自在自己的工作内存中创建属于当前线程的本地变量,当然也包括了字节码行号指示器、相关Native方法的信息。
注意由于工作内存是每个线程的私有数据,线程间无法相互访问工作内存,因此存储在工作内存的数据不存在线程安全问题。
JMM中的八种操作?
为了支持 JMM,Java 定义了8种原子操作,用来控制主存与工作内存之间的交互:
1.lock(锁定)
lock作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
2.unlock(解锁)
unlock作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
3.read(读取)
read作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。
4.load(载入)
load作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
5.use(使用)
use作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
6.assign(赋值)
assign作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
7.store(存储)
store作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用。
8.write(写入)
write作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》