下面的代码是Java中线程安全的Singleton模式的正确示例吗?
class Singleton {
private static Singleton INSTANCE = new Singleton();
public static Singleton getInstance() {
return INSTANCE;
}
}
由于静态成员仅在一次由JVM加载的类中被初始化(这保证是线程安全的)时才被初始化,所以上面的代码示例不是线程安全的Singleton类(早期加载)吗?
以上声明有什么问题吗?如果是,那么将其转换为线程安全的Singleton类需要进行哪些最小更改?
最佳答案
JLS保证这是安全的。请参见the holder pattern:“由于JLS保证类的初始化阶段是连续的,即非并发的,因此在加载和初始化期间,静态getInstance方法中不需要进一步的同步。”
持有人模式比您想要的要复杂,但是重要的部分是static final Something INSTANCE = new Something()
不管在哪个类中声明都是安全的。与您拥有的人相比,持有人模式的好处是单例不会被初始化第一次使用。如果在初始化Singleton
实例的成本很高时,要访问Singleton
类中的其他静态成员,这将很有帮助。
正如Lewis_McReu和user6690200指出的那样,您应该声明INSTANCE
字段final
,以确保您不会意外地为变量分配其他Singleton
实例。您还应该声明一个私有的无参数Singleton()
构造函数,以防止创建其他实例。为了使它更加防弹,您应该声明Singleton
类final
,以便不能使用public
构造函数对其进行子类化。