我最近偶然看到一篇文章讨论了Java中的双重检查锁定模式及其缺陷,现在我想知道我已经使用多年的这种模式的变体是否存在任何问题
我看过很多关于这个主题的帖子和文章,了解了获取对部分构造对象的引用的潜在问题,就我所知,我不认为我的实现会受到这些问题的影响。以下模式是否存在任何问题
如果不是,为什么人们不使用它?我从来没有在我所看到的关于这个问题的任何讨论中看到过它被推荐
公共类测试{
私有静态测试实例;
私有静态布尔初始化=false;
公共静态测试getInstance(){
如果(!已初始化){
同步(Test.class){
如果(!已初始化){
实例=新测试();
初始化=真;
}
}
}
返回实例;
}
}
双重检查锁是否损坏。由于initialized是一个原语,它可能不要求它是易失性的才能工作,但是在初始化实例之前,没有任何东西可以阻止initialized被视为非同步代码的true
编辑:为了澄清上述答案,最初的问题是关于使用布尔值控制双重检查锁定。如果没有上面链接中的解决方案,它将无法工作。您可以在实际设置布尔值时双重检查锁,但在创建类实例时,仍然存在指令重新排序的问题。建议的解决方案不起作用,因为在非同步块中看到已初始化的布尔值为true后,可能无法初始化实例
双重检查锁定的正确解决方案是要么使用volatile(在实例字段上)并忘记初始化的布尔值,确保使用JDK 1.5或更高版本,要么在最后一个字段中初始化它,如链接文章和Tom的答案中所述,或者干脆不使用它
当然,整个概念看起来像是一个巨大的过早优化,除非您知道在获得这个单例时会遇到大量的线程争用,或者您已经分析了应用程序,并看到这是一个热点