- 特性:内存可见性和防止指令重排(实现线程安全)
- 什么是内存可见性
--首先我们要了解在多线程的并发的场景下可能会出现的问题,得先清楚什么JMM(内存模型)
内存模型:在多线程场景下,共享的变量放在主内存空间中,每个线程会开辟一份工作内存空间,将主内存的变量复制一份,各线程操作各自的工作内存空间变量然后写回主内存。
JMM有关同步的规定:
- 线程解锁前,必须把共享变量的值刷新回主内存;
- 线程加锁前,必须读取主内存的最新值到自己的工作内存中;
- 加锁和解锁使用的是同一把锁;
但这就容易出现缓存一致性问题,为了解决这一问题,可以遵循MESI规范协议(CPU在写数据时,通知其他CUP将该变量的缓存行设置无效,其他CUP在读取变量的时候发现缓存该变量的缓存行无效则重新从主内存读取。)如何发现该变量的缓存行无效呢,这就使用了总线嗅探技术(不间断的判断缓存行对应的内存地址是否发生改变,如果改变则认为无效)
内存可见性就是一个线程修改了主内存的变量后,其他线程立马就知道,并且重新获取更新后的值。
- 什么是指令重排
-- 程序最终回转化为指令由CPU去执行,在不改变程序结果的前提下,为了提高性能,编译器和和处理器通常会对指令进行指令重排序,可能执行顺序为:2—1—3—4,也可能是:1—3—2—4,一般分为下面三种:
禁止指令重排序的原理:因为在volatile会在指令之间插入一条内存屏障指令,通过内存屏障指令告诉CPU和编译器不管什么指令,都不进行指令重新排序。也就说说通过插入的内存屏障禁止在内存屏障前后的指令执行指令重新排序优化。
什么是内存屏障
内存屏障是一个CPU指令,他的作用有两个:
- 保证特定操作的执行顺序;
- 保证某些变量的内存可见性;