Java,懒惰地初始化字段而没有同步

And*_*rey 6 java synchronization lazy-evaluation

有时当我需要懒惰的初始化字段时,我使用以下设计模式.

class DictionaryHolder {
  private volatile Dictionary dict; // some heavy object

  public Dictionary getDictionary() {
    Dictionary d = this.dict;
    if (d == null) {
      d = loadDictionary(); // costy operation
      this.dict = d;
    }
    return d;
  }
}
Run Code Online (Sandbox Code Playgroud)

它看起来像Double Checking idion,但不完全是.没有同步,可以loadDictionary多次调用方法.

当并发性很低时我使用这种模式.在使用此模式时,我还要记住以下假设:

  • loadDictionary 方法始终返回相同的数据.
  • loadDictionary 方法是线程安全的.

我的问题:

  1. 这种模式是否正确?换句话说,是否可以getDictionary()返回无效数据?
  2. 是否有可能使dict现场非挥发性更高效?
  3. 有没有更好的解决方案?

axt*_*avt 2

1.这个模式正确吗?换句话说,getDictionary()有可能返回无效数据吗?

是的,如果可以的话,loadDictionary()可以由多个线程同时调用,因此不同的调用可以getDictionary()返回不同的对象。否则,您需要一个具有同步功能的解决方案。

2.是否可以使 dict 字段成为非易失性以提高效率?

不,它可能会导致内存可见性问题。

3.有没有更好的解决办法?

只要您想要一个没有同步的解决方案(显式或隐式) - 不(据我了解)。否则,有很多习惯用法,例如使用enum或内部持有者类(但它们使用隐式同步)。