双重锁实现单例时遭到质疑,既是:双重锁也无法保证实例模式!
果然,答案又是对方对的,汗颜!
原因是:指令会重排序,普通的变量仅仅会保证该方法在执行时,所有依赖的赋值结果是正确的,但不会保证执行顺序!
为什么会重排序:指令重排序是指cpu采用了允许将多条指令不按照程序的顺序分开发送各相应电路单元处理,cpu不会任意排序(深入java虚拟机第12章),但需要重排序提高性能。
怎么解决,标题也写明白了。
使用volatile关键字!
为什么使用volatile关键字可以实现:此关键字会禁止指令重排序,即:增加了内存屏障!
如果是一个cpu内存屏障是毫无意义的,如果是多cpu访问同一块内存,并且其中一个在观测另一个,就需要内存屏障来保证一执行了。
如果你打开编译后的代码清单,会看到加入volatile关键字的变量会多一条指令:lock addl $0x0 ,(%esp)
此指令很有意义:lock addl $0x0 指令的作用是使当前cpu的cache值写入内存,该写入操作也会引起其他cpu或者内核无效化其cache,既是是做了一个空操作(store、write),可以让volatile变量对其他cpu立即可见!
1 public class Singleton { 2 3 private volatile static Singleton singleton = null; 4 5 public static Singleton getSingleton() { 6 if (singleton == null) { 7 synchronized (Singleton.class) { 8 if (singleton == null) { 9 singleton = new Singleton();10 }11 }12 }13 return singleton;14 }15 }
View Code
另外:volatile屏蔽指令重排序的语义,在jdk1.5中才被完全修复!
原标题:volatile双重锁实现单例
关键词: