由于双锁检查不适用于优化的编译器,因此我将其从单例类中删除,而不是进行早期初始化。
下面是我的新单身人士课:
class MySingleton {
private static volatile MySingleton myInstance = new MySingleton();
public static getInstance() {
return myInstance;
}
}
除了getInstance()之外,该类中还有setter方法,用于设置成员字段的值。
希望当多个线程将使用同一对象更新各种成员字段时,此实现不会导致任何数据不一致。
欢迎任何建议或投入。
答案 0 :(得分:3)
此代码是线程安全的。实际上,您可以删除volatile
,它仍然是线程安全的。
在第一次myInstance
调用触发静态初始化(如果尚未发生)时,将初始化getInstance
变量。在初始化和第一次调用之前有一个 happens-before 。
但是,您也这样说:
希望当多个线程将使用同一对象更新各种成员字段时,此实现不会导致任何数据不一致。
您尚未显示用于执行此操作的任何代码,因此我们无法告诉您那个代码是否是线程安全的。如果MySingleton
实例是可变的,则状态相关的方法必须适当地同步,以防止出现内存危险和争用条件。您显示给我们的代码无法解决此问题。
由于默认的MySingleton
构造函数是public
,因此这不是适当的单例类。可以创建多个实例。
此实现与许多其他实现的不同之处在于,抢先而非延迟地创建了独特的MySingleton
实例。这大大简化了问题。
请注意,单例的惰性初始化通常是不必要的。如果您不需要专门的延迟初始化,那么更简单的替代方法就可以了。
答案 1 :(得分:0)
您的单例是线程安全的,但是除了调用getInstance()
以外,还有其他事情可能导致MySingleton
类被初始化,从而构造了实例。
通常的解决方法是将单例放在这样的私有嵌套类中:
class MySingleton {
private MySingleton() {
// there can only be one
}
private static class Holder {
static final MySingleton instance = new MySingleton();
}
public static MySingleton getInstance() {
return Holder.instance;
}
}
现在,只能在初始化Holder
类时构造该实例,并且仅在第一次调用getInstance()