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关键字。