我想写一个实例方法来懒惰地初始化几个静态变量。我初始化的对象是不可变的,对象的引用不会被类中的任何其他实例或静态方法改变。我希望初始化代码永远不会被执行多次,即使在许多不同的线程中可能有多个类的实例。初始化需要在实例方法中进行,因为该方法会覆盖超类中的方法。我正在使用的方法如下。在多线程情况下懒惰地初始化静态变量
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;
}
}
我假设从初始化发生在一个synchronized块,那将是不可能的实例来不断观察isPrepared
为true
除非object1
,object2
和object3
都是非空。我还假设它不会工作,只需声明prepare()
为锁定为this
。我的假设是正确的吗?另外,当你想将它们视为一起初始化时,是否有一个标记为volatile
的变量是一个好主意,还是应该将它们组合成一个Immutable类?
感谢您的回答。我想我会使用将变量绑定到单个易变变量的方法。但是,是不是volatile和synchronized block的组合是完全消除你提到的重复的可能性的最简单方法? – 2014-11-25 12:40:09
是的。首先检查volatile var的值,然后根据需要输入synchronized块。 – 2014-11-25 12:49:35
好点。如果var已经存在,你不想等待其他线程。您是否需要检查volatile var的值两次,一次查看是否需要同步块,以及一次是否在块的开头?由于初始检查不同步,因此在进入同步块时,初始化可能已在另一个线程中完成。 – 2014-11-25 13:00:46