Java double checked locking(Java 双重检查锁定)
问题描述
我最近偶然看到一篇文章,讨论了 Java 中的双重检查锁定模式及其陷阱,现在我想知道我多年来一直使用的该模式的变体是否会遇到任何问题.
I happened upon an article recently discussing the double checked locking pattern in Java and its pitfalls and now I'm wondering if a variant of that pattern that I've been using for years now is subject to any issues.
我查看了许多有关该主题的帖子和文章,并了解获取对部分构造对象的引用的潜在问题,据我所知,我不认为我的实施受这些问题的影响.以下模式有什么问题吗?
I've looked at many posts and articles on the subject and understand the potential issues with getting a reference to a partially constructed object, and as far as I can tell, I don't think my implementation is subject to these issues. Are there any issues with the following pattern?
如果没有,为什么人们不使用它?在我看到的有关此问题的任何讨论中,我从未见过有人推荐过它.
And, if not, why don't people use it? I've never seen it recommended in any of the discussion I've seen around this issue.
public class Test {
private static Test instance;
private static boolean initialized = false;
public static Test getInstance() {
if (!initialized) {
synchronized (Test.class) {
if (!initialized) {
instance = new Test();
initialized = true;
}
}
}
return instance;
}
}
推荐答案
双重检查锁定已损坏.由于 initialized 是一个原语,它可能不需要它是 volatile 才能工作,但是没有什么可以阻止在实例初始化之前将 initialized 视为非同步代码的真实情况.
Double check locking is broken. Since initialized is a primitive, it may not require it to be volatile to work, however nothing prevents initialized being seen as true to the non-syncronized code before instance is initialized.
为了澄清上述答案,原始问题询问了有关使用布尔值控制双重检查锁定的问题.如果没有上面链接中的解决方案,它将无法正常工作.您可以仔细检查 lock 是否实际设置了一个布尔值,但在创建类实例时仍然存在指令重新排序的问题.建议的解决方案不起作用,因为在非同步块中看到初始化的布尔值为 true 后,可能无法初始化实例.
To clarify the above answer, the original question asked about using a boolean to control the double check locking. Without the solutions in the link above, it will not work. You could double check lock actually setting a boolean, but you still have issues about instruction reordering when it comes to creating the class instance. The suggested solution does not work because instance may not be initialized after you see the initialized boolean as true in the non-syncronized block.
双重检查锁定的正确解决方案是使用 volatile(在实例字段上)并忘记初始化的布尔值,并确保使用 JDK 1.5 或更高版本,或者在 final 字段中初始化它,详细说明在链接的文章和汤姆的答案中,或者只是不使用它.
The proper solution to double-check locking is to either use volatile (on the instance field) and forget about the initialized boolean, and be sure to be using JDK 1.5 or greater, or initialize it in a final field, as elaborated in the linked article and Tom's answer, or just don't use it.
当然,整个概念似乎是一个巨大的过早优化,除非您知道在获取此 Singleton 时会发生大量线程争用,或者您已对应用程序进行了概要分析并认为这是一个热点.
Certainly the whole concept seems like a huge premature optimization unless you know you are going to get a ton of thread contention on getting this Singleton, or you have profiled the application and have seen this to be a hot spot.
这篇关于Java 双重检查锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Java 双重检查锁定
基础教程推荐
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01