阎宏在《Java与模式》强烈建议大家不要再花时间在实现双重检查成例上,理由是:
“令人吃惊的是,在C语言里得到普遍应用的双重检查成例在多数的Java语言编译器里并不成立。上面使用了双重检查成例的“懒汉式”单例类,不能工作的基本原因在于,在Java编译器中,LazySingleton类的初始化与m_instance变量赋值的顺序不可预料。如果一个线程在没有同步化的条件下读取m_instance引用,并调用这个对象的方法的话,可能会发现对象的初始化过程尚未完成,从而造成崩溃。”
1 public class LazySingleton 2 { 3 private static LazySingleton m_instance = null; 4 private LazySingleton(){} 5 public static LazySingleton getInstance() 6 { 7 if(m_instance == null) 8 { 9 synchronized(LazySingleton.class) 10 { 11 if(m_instance == null) 12 { 13 m_instance = new LazySingleton(); 14 } 15 } 16 } 17 return m_instance; 18 } 19}
我看了不是很明白,是不是指new LazySingleton()在执行构造函数和m_instance = ....这个赋值语句的顺序不确定。可能会出现new LazySingleton() 先分配好内存地址,然的执行了 m_instance = “内存地址”,再执行构造函数里的代码,这样会造成m_instance先被赋了值。其它线程一量这时候访问第7行就会出错。如果是这样,我们是不是可以改成以下: 1 public class LazySingleton 2 { 3 private static LazySingleton m_instance = null; 4 private LazySingleton(){} 5 public static LazySingleton getInstance() 6 { 7 if(m_instance == null) 8 { 9 synchronized(LazySingleton.class) 10 { 11 if(m_instance == null) 12 { 13 LazySingleton temp = new LazySingleton(); 14 m_instance = temp; 15 } 16 } 17 } 18 return m_instance; 19 } 20} 实在是不太清楚,请高手指教。
|
|