懒惰地在多线程情况下初始化静态变量

时间:2014-11-25 11:47:24

标签: java synchronized volatile static-variables

我正在尝试编写一个实例方法来懒惰地初始化几个静态变量。我初始化的对象是不可变的,并且对象的引用不会被类中的任何其他实例或静态方法更改。我希望初始化代码永远不会被执行多次,即使在许多不同的线程中可能有多个类的实例。初始化需要在实例方法中进行,因为该方法会覆盖超类中的方法。我使用的方法如下。

private static volatile boolean isPrepared;
private static volatile Object object1;
private static volatile Object object2;
private static volatile Object object3;

@Override
void prepare() {
    synchronized (this.getClass()) {
        if (isPrepared) { return; }
        object1 = expensiveCalculation1();
        object2 = expensiveCalculation2();
        object3 = expensiveCalculation3();
        isPrepared = true;
    }   
}

我假设由于初始化发生在一个同步的块中,因此实例不可能将isPrepared视为true,除非object1,{{1 }和object2都是非空的。我也假设它只是将object3声明为prepare(),因为锁只是synchronized而无法工作。我的假设是对的吗?另外,当你想将它们视为一起初始化时,将几个变量标记为this是一个好主意,还是应该将它们捆绑在一起成为一个不可变类?

2 个答案:

答案 0 :(得分:1)

将所有延迟初始化状态捆绑为不可变对象通常是首选方法,因为您需要的所有volatile变量,没有同步。如果另一个线程在初始化过程中开始初始化,那么这种安排会让你有一些重复的努力,但是可以最小化它的可能性,例如通过将一个标记值写入volatile来发出信号" in进展"州。

答案 1 :(得分:0)

您可以使用下一种方法:https://stackoverflow.com/a/11879164/2413618 将变量放入静态嵌套类中。当第一次访问嵌套类时,将初始化所有变量。