我有一个类似静态var的类
private static Object sMyStaticVar;
如果我想在构造函数中为此var赋值,我有像
这样的代码if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
其中someRuntimeObject
是一个在我的类加载时不可用的对象,因此阻止我声明我的静态var,如下所示
private static Object sMyStaticVar = new CustomObject(someRuntimeObject);
我的问题是,构造函数线程中的静态var对象的初始化是否安全?我的直觉告诉我它不是,我应该使用非运行时类类型作为锁同步,如下所示
synchronized(MyClass.class)
{
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
}
(与从getClass()
获得的runTime类型相反)
但由于我的直觉通常是错误的,如果有人能为我阐明这一点,我将不胜感激!
答案 0 :(得分:3)
如果它是静态的,则不应在构造函数中指定它。创建一个执行public static synchronized void initialize(someRuntimeObject)
的静态初始化方法。
请注意synchronized
关键字:它与MyClass.class
上的同步
答案 1 :(得分:1)
你是对的,以下是对竞争条件开放的:
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
两个主题可以同时检查sMyStaticVar
,查看null
,创建两个对象等...
这意味着您需要同步。您可以在某个现有对象上进行同步(有多个选项),或者您可以仅为prurpose创建一个对象,这样您就不必与其他任何人共享锁定,从而冒着不必要的争用:
private static Object sMyStaticVar;
private static Object sMyStaticVarLock = new Object();
然后,在构造函数中:
synchronized(sMyStaticVarLock)
{
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
}
答案 2 :(得分:1)
需要进行此同步,但这不足以实现线程安全。
访问时,您还需要确保字段值的可见性。因此,您应该将该字段声明为volatile
,或者为该字段的每次访问添加相同的同步。