是的, 您应该绝对同步化( 或者使用像 < a href=" http:// en. wikipedia. org/ wiki/ Intiatalization- on- demand_ desistr_ idiom" rel = “ nofollow” @ em > Singleton Holder idiom em/ / a > 这样的更好的语句 。 否则, 您将面临多个线条对对象进行多次初始化的风险( 然后再使用不同实例 ) 。
想想这样的一系列事件:
- Thread A enters
getMyObj()
and sees that obj == null
- Thread B enters
getMyObj()
and sees that obj == null
- Thread A constructs a
new MyObj()
- let s call it objA
- Thread B constructs a
new MyObj()
- let s call it objB
- Thread A assigns
objA
to obj
- Thread B assigns
objB
to obj
(which is not null
anymore at this point, so the reference to objA
, assigned by Thread A, is overwritten)
- Thread A exits
getMyObj()
and starts to use objA
- Thread B exits
getMyObj()
and starts to use objB
这种情景可能随任何几条线而发生。 请注意,虽然为了简单起见,我假设在真实的多读环境事件1-2、3-4和/或7-8中,我假设了严格的事件顺序,但时间上可以部分或完全重叠,而不会改变最终结果。
持单人名词的一个例子:
public class Something {
private Something() {
}
private static class LazyHolder {
public static final Something INSTANCE = new Something();
}
public static Something getInstance() {
return LazyHolder.INSTANCE;
}
}
由于 inSTance
是 final
。 Java 内存模型保证,在装入包含类时, final
字段初始化,并正确显示于任何数条线条上。由于 LazyHolder
是 私人的
,且仅由 getInstance ()
引用,因此只有在首先调用 getInstance ()
时才被装入。 此时, instance < ()
在背景中初始化,并由JVM 安全发布。