JMM:(java内存模型)
Volatile保证线程间的共享变量可见性和有序性,可见性底层是基于lock指令实现的,
计算机进行指令重排会基于as-if-serial和happens-before原则
as-if-serial:
就是说不管怎么重排,在单线程下,最终运行结构得和顺序运行结果相同,也就是说后面的语句不依赖于前面的语句,就可以重排,但是在多线程情况下,两个线程之间的依赖它实际是控制不了的,所以会出错。
happens-before:(8种,就是规定了8种原则不能重排序)比如
锁规则:就是说解锁一定要发生在同一个锁再一次调用之前
对象的创建流程:
先检查是否已加载类,没加载就加载,加载了就分配堆内存,然后初始化,设置对象头,执行init(C++实现)方法,其实在执行init方法时才是真正的进行赋值。比如说懒汉式单例模式,线程一加锁过后对对象进行创建,如果说指令重排将对象的创建地址分配提前了,而此时线程二进入进行第一次判断,发现该对象有地址,会误以为已经实例化,然后使用时发现对应属性还没有赋值,所以这里要使用volatile进行禁止指令重排
上述问题需要用到volatile,内存屏障:
内存屏障就是说在在放置内存屏障附近的代码不能进行指令重排,
四种屏障:用来避免指令重排,比如a是valatie修饰的变量
StoreStore屏障, 就是说在执行a=1操作之前有的语句要先执行
a=1; 对a进行写操作,则前面会加上StoreStore屏障
StoreLoad屏障, 就是说在执行之后的操作要保证a=1以及执行并刷入主内存,
b=a;对a进行写操作,在之后加上LoadLoad屏障
LoadLoad屏障,就是说b=a这个读取操作要在后续读取操作之前
LoadStore屏障,就是后续的对a进行写操作,要保证b=a读操作已经进行完
屏障的底层就是使用的lock指令