java 的double-check locking

《Java与模式》在讲Lazy Singleton时,提到在c++单例中广泛使用的double-checl locking,在java中确实无效的:
    “在Java编译器中,LazySingleton类的初始化与m_instance变量赋值的顺序不可预料。如果一个线程在没有同步化的条件下读取m_instance引用,并调用这个对象的方法的话,可能会发现对象的初始化过程尚未完成,从而造成崩溃。”
    
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;   
    }   

这段话是说,是jvm执行时会对便以后的字节码重排序(reordering),最坏的情况下,当m_instance被赋值以后(不为null,过了里面的那层检查),LazySingleton类其实还没有完成初始化,那么对m_instance中成员的访问就会导致错误。当然这种是极少发生的,在这个问题被发现之前java的double-check locking也曾大行其道。
阎宏写《Java与模式》的时候java还在1.4的版本。当java1.5发布以后,情况发生了一点改变。java的double check也是可行的了。只要LazySingleton的所有instance field都是immutable的话,就能保证成功了。在Java5之后,有一个所谓的“happens-before”的概念,在每一个构造函数结束的地方都有一个freeze动作,在构造函数返回前,所有的final成员变量都要完成初始化。使用volatile来修饰static的m_instance也可以保证成功,然而一些jvm并没有正确实现volatile语义,所以这种发放还不是那么保险。官方的说法是:
"In JVMs prior to 1.5, volatile would not ensure that it worked (your mileage may vary). Under the new memory model, making the instance field volatile will "fix" the problems with double-checked locking, because then there will be a happens-before relationship between the initialization of the Something by the constructing thread and the return of its value by the thread that reads it."

按照java专家们的习惯,java中会出问题的东西,一定是不好的东西。JSR 166专家组说,double-checked locking是一种不好的发明,现在已经被广泛废弃。替代是Lazy initialization holder,提供了同样的好处,也更容易理解。Effective Java中有个例子 
public class Foo {
    private static class FooHolder { 
        static final Foo foo = new Foo(); 
    } 
    public static Foo getFoo() {
        return FooHolder.foo;
    } 
}
这是个很triky的方法,利用了jvm类加载时的特性,第一次使用FooHolder时才进行初始化。不得不承认,看起来确实比double-checked locking简单舒服一些。


http://hi.baidu.com/%BA%FA%D2%E7%D1%F3/blog/item/24e14e4aeabd762b09f7ef81.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值