volatile如何保证可见性和防止重排序

1 保证可见性:

内存可见性是指一个CPU对数据修改,对其他CPU立即可见。

(1)”CPU对数据修改“:

CPU对数据的修改总是先修改工作内存,然后再同步回主内存,只不过是对被volatile修饰变量的修改,会立刻同步回主内存。

(2)”对其他CPU立即可见“:

当CPU_A修改完volatile变量,并且立即同步回主存,如果CPU_B的工作内存中也缓存了这个变量,那么B的这个变量将立即失效,当B想要修改这个变量的时候,B必须从主存重新获取变量的值。

实现原理:

基于CPU的MESI协议(缓存一致性协议),其中M表示Modify,E表示独占Exclusive,S表示Shared,I表示Invalid。如果一个CPU修改了数据,那么这个CPU的数据状态就会更新成M,同时其他CPU上的数据状态更新成I,这个是通过CPU多核之间的嗅探机制实现的。

2 防止重排序:

实现原理:

内存屏障(Memory Barrier),像一套栅栏分割前后的代码,阻止栅栏前后的没有数据依赖性的代码进行指令重排序,保证程序在一定程度上的有序性。

在单例模式中,Instance inst = new Instance();   这一句代码不是原子操作,它可以分成三步原子指令:

(1)分配内存地址;

(2)new一个Instance对象;

(3)将内存地址赋值给inst;

CPU为了提高执行效率,这三步操作的顺序可以是123,也可以是132。如果是132顺序的话,当把内存地址赋给inst后,inst指向的内存地址上面还没有new出来单例对象,这时候,如果就拿到inst的话,它其实就是空的,会报空指针异常。这就是为什么双重检查单例模式中,单例对象要加上volatile关键字。

猜你喜欢

转载自blog.csdn.net/u012906122/article/details/103414321