别只知道JVM 而不知道JMM
JAVA 内存模型--JMM
内存模型概念:在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象
JMM:主要就是因为CPU的多核多级缓存 为了优化代码而进行的指令重排序 从而处理器会对代码乱序的问题。保证最终的并发安全。JMM是一个抽象的概念 抽象出了工作内存存于主内存的概念 并且规定了一些操作来实现主内存的变量到线程的变量和线程之间的变量之间的交互动作的实现
- -主内存里面的变量是共享的
- 线程与线程之间的变量是不能交互的 但可以通过主内存进行变相的交互动作
- 每个变量都有自己的工作内存里面是保存该线程使用到的变量的主内存的拷贝
- 线程对变量的操作都是在工作内存里面完成的
规定了一些操作☞的是(八大原子操作):
- - Lock操作(把该主内存的变量锁上为当前锁定的线程使用)
- Unlock操作(谁锁的谁来进行释放锁)
- Read操作 把主内存的变量的值读取到工作内存(当前只是拿到而没有放到那个线程的变量里面)
- Load操作载入 把read读取到的值放入到工作内存的变量副本里面去 所以主内存变量的值到线程工作内存的变量副本是根据两个动作接力(read+load)完成的
- Use操作 把获取到的变量副本值给执行引擎(执行引擎就是一个把变量的值进行计算操作在输出一个新的值的一个东西)
- Assign赋值操作 把执行引擎给的值返回去变量副本
- Store 存储操作 把工作内存中的变量副本的值传给主内存的变量
- Write 操作 把store拿到的值写入到主内存变量里面去
内存之间交互的规则
重排序:
是什么:是编译器或处理器为了优化程序的性能,对指令执行的顺序进行重新排列的一种手段
目的:就是为了优化程序的执行性能
分类:编译器优化重排序(编译器在不改变程序在单线程环境下运行的语义的前提下 可以重新安排语句的执行顺序---目的:尽可能减少寄存器的读取,存储次数,复用寄存器存储的数据)
指令级并行重排序(处理器将多条指令并行执行,如果不存在数据依赖,处理器可以改变语句对应的指令的执行顺序)
内存系统的重排序(处理器使用缓存和读写缓冲区使得数据的加载,存储操作,看上去是乱迅执行的)
as-if-serial规则
不管有没有重排序,也不关心如何进行的重排序 单线程环境下,程序的执行结果不会被改变
编译器,JVM,处理器都准守这个语义
happens-before规则
是什么:用来保障两个操作之间的可见性 保证多线程之间运行有序的跑
包括:
- 程序顺序规则:意思是任意的前一个操作不一定一定要在后操作的前面 但是前操作的结果一定要在对后操作可见,意思是两个人比赛跑步AB,A不一定先比B跑 B也可以先跑 但是必须A要先到终点获得结果,不满足就不能进行重排序
- 锁规则:锁的解锁要在锁的加锁之前
- Volatile变量的规则:对一个volatile修饰的属性进行的写操作 happens-before 任意后续对这个volatile修饰的属性的字段的读操作
- 传递性 A happens-before B B happens-before C 所以A happens-before C
- Start规则:如果在线程A里面执行线程B的start 那么在线程A里面的B.start操作 happens-before 线程B里面的任意操作(一个线程要执行里的操作肯定要先启动哇)
- Join规则:如果线程A执行了线程B的join 的方法 一样要优先级高于线程B里面的任意操作
内存屏障(JMM的八大原子动作保证了并发语义关键字的代码能够实现对应的安全并发访问)
官方观点:
自己的简易理解:
内存屏障是硬件之上、操作系统或JVM之下,对并发作出的最后一层支持, 这个东西就是一个指令操作 去防止出现一些事情的发生。