【发布时间】:2018-11-30 18:56:33
【问题描述】:
我不明白为什么这里需要局部变量:
public class FinalWrapper<T> {
public final T value;
public FinalWrapper(T value) {
this.value = value;
}
}
public class Foo {
private FinalWrapper<Helper> helperWrapper;
public Helper getHelper() {
FinalWrapper<Helper> tempWrapper = helperWrapper;
if (tempWrapper == null) {
synchronized(this) {
if (helperWrapper == null) {
helperWrapper = new FinalWrapper<Helper>(new Helper());
}
tempWrapper = helperWrapper;
}
}
return tempWrapper.value;
}
}
此代码来自:https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java。如果我们没有这个局部变量,我们会遇到什么问题?根据维基文章:
Java 5 中 final 字段的语义可用于安全地发布帮助对象,而无需使用 volatile。局部变量 tempWrapper 是正确性所必需的:简单地使用 helperWrapper 进行 null 检查和 return 语句可能会由于 Java 内存模型下允许的读取重新排序而失败。此实现的性能不一定比 volatile 实现更好。
提前致谢。
【问题讨论】:
-
你最好使用嵌套私有类的惰性持有者习惯用法,它通过类加载机制强制执行单例行为。
-
我在下面更新了我的答案,以提供有关重新排序的更多信息。我希望它会耗尽主题。
标签: java concurrency singleton final