构造函数中的同步块

时间:2011-11-03 11:10:06

标签: java multithreading

我有一个类似静态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类型相反)

但由于我的直觉通常是错误的,如果有人能为我阐明这一点,我将不胜感激!

3 个答案:

答案 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,或者为该字段的每次访问添加相同的同步。