public class LazySingleton { private static LazySingleton m_instance = null; private LazySingleton(){} //静态工厂方法 public static LazySingleton getInstance(){ if(m_instance == null){ synchronized (LazySingleton.class) { if(m_instance == null){ m_instance = new LazySingleton(); } } } return m_instance; } }上面是一段使用双重检查成例的懒汉式单例类。 大家能告诉我下面的说法对吗?在系统中有可能发生吗? 在Java编译器中,由于m_instance变量的赋值和LazySingleton类的初始化顺序是不确定的,所以某线程读取m_instance的引用,调用这个对象的方法时,对象的初始化尚未完成(也就是,m_instance = new LazySingleton();这段中的new LazySingleton()还没有执行完)导致出现错误。
构造方法里Thread.sleep(10),模拟下类的构造过程,用多线程去getInstance(),再print(m_instance),就会发现地址值不一样了,说明构造了多个对象,这么写就是防止这种情况。其实也并不需要用DCL这种方式,饿汉模式就能避免这种情况。######嗯嗯 sleep() 要的就是这个 非常感谢######个人是这么理解的,假如有两个线程 A,B同时调用 getInstance方法,当A线程运行到代码第6行时,时间片被撤出,B线程运行getInstance方法,拿到锁之后,对变量进行赋值,这是为了防止多线程的情况下,会造成建立多个对象。###### private static LazySingleton m_instance = new LazySingleton(); 这样简单
######嗯 饿汉式单例和带有同步机制的懒汉式单例都应该没问题######如果初始化开销大,这种方式就不太好。但是一般的,这种方式比较好。我也喜欢这种方式。###### 对的 可以参考《Java concurrency in practice》16.2.4节
如果必须实现lazy initialization,可以利用JVM的lazy class loading机制。 ######额 我找找这本书######写两个线程,打个断点不就可以观察了吗?或者在 if(m_instance == null)后面sleep()几秒,如果没有双重检查,你就会看到两个线程分别分别产生了不同的对象,二者拿到的对象不是同一个,因此不能保证单例######sleep正中靶心###### Intuitively, this algorithm seems like an efficient solution to the problem. However, this technique has many subtle problems and should usually be avoided. For example, consider the following sequence of events:
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。