初始化非最终静态变量是否是线程安全的?

时间:2015-03-07 23:18:48

标签: java concurrency

假设我有一个私有的非final静态变量,并在静态块中初始化,并且在初始化后没有修改它,并且没有修改变量的方法。它是线程安全的吗?

class Test
{
     private static int value = 10;

     public static int getValue()
     {
        return value;
     }
 }

1 个答案:

答案 0 :(得分:1)

  

我只想知道JVM对非最终静态变量提供什么保证,没有方法在线程安全性方面修改变量,多线程尝试读取数据。

初始化类(JLS 11.4.2)的过程表明在保持锁定的同时执行初始化。我认为这意味着在初始化完成后引用静态的任何线程都将看到完全初始化的状态。

如果您遇到一个类的静态初始化并且启动了一个可以在后者的静态初始化完成之前观察到另一个类的静态变量的线程,则可能会遇到麻烦。在这种情况下,可能无法保证线程将看到初始化状态。


另一个需要注意的是,我们这里只讨论静态变量中的值。如果这些变量引用可变对象或数组,并且这些对象/数组发生了变异,则代码不会自动进行线程安全。

这说明了一个更大的观点。实际上,您无法单独讨论变量的线程安全性。线程安全的公认定义是引入线程不会导致某些事情的错误行为。变量没有行为。行为是应用程序级别的事情,尽管考虑应用程序的一部分的行为有时是有意义的;例如特定应用程序上下文中的某些类或方法。


在行之间阅读......你似乎试图避免使用静态的同步“开销”。这一切都很好......但是线程安全,静态初始化和内存模型都是Java语言中最困难/难以理解的部分。许多真正聪明的人(过去)在实施“聪明”或“有效”的方法来减少同步开销时尝试失败。

我的建议:不要试图太聪明。把事情简单化。同步开销不够大(IMO),有可能将“heisenbugs”引入代码库。

最后,人们普遍认为静态变量,尤其是可变静态变量是糟糕的OO设计。我建议你考虑修改你的设计以消除它们。