让我们有一个类定义,如
public static class Bootstrapper {
public static final Object DEFAULT_VALUE = getDefaultValue();
private static Object getDefaultValue() {
if (DEFAULT_VALUE == null) {
return createValue(); // Not thread safe
}
return DEFAULT_VALUE;
}
}
其中createValue()
方法未引用DEFAULT_VALUE
字段,仅在Bootstrapper
类的构造函数中调用,并且不是线程安全的。
上述代码是否有任何问题(除了编程风格)?考虑到类初始化的规则,假设线程安全不是问题,但程序员需要注意哪些重要事项?
答案 0 :(得分:3)
正如Augusto所解释的那样,您的代码是线程安全的。但它相当令人费解。它在功能上是等效的,稍微更高效,并且更简单地做到这一点:
public static class Bootstrapper {
private static final Object DEFAULT_VALUE = createValue();
public static Object getDefaultValue() {
return DEFAULT_VALUE;
}
}
编辑:我也注意到该字段是公开的,而getter是私有的。这应该是另一种方式。
答案 1 :(得分:2)
从线程的角度来看这是安全的,因为类加载是线程安全的,并且将设置该值(因此getDefaultValue()
)将在加载类之后调用,但在它离开类加载之前代码。
要回答PNS对上述原始问题的评论,如果该类由2个不同的类加载器加载,则无论如何都会遇到麻烦,因为使用synchronized
上的getDefaultValue()
关键字会在类上创建锁定......因为你有2个班级,每个班级都是完全独立的。您可以在Java语言规范的 4.3.4参考类型相同(适用于JLS 8)一节中阅读本文。