Java,没有同步的延迟初始化字段

标签 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;
  }
}

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

我在并发性很低的时候使用这个模式。在使用此模式时,我还要牢记以下假设:

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

我的问题:

  1. 这个模式正确吗?换句话说,getDictionary() 是否可能返回无效数据?
  2. 是否可以使 dict 字段保持非 volatile 以提高效率?
  3. 有没有更好的解决方案?

最佳答案

我个人觉得Initialization on demand holder idiom很适合这种情况。来自维基:

public class Something {

        private Something() {}

        private static class LazyHolder {
                private static final Something INSTANCE = new Something();
        }

        public static final Something getInstance() {
                return LazyHolder.INSTANCE;
        }
}

虽然这看起来像是一种纯粹用于单例控制的模式,但您可以用它做很多更酷的事情。例如holder 类可以调用一个方法,该方法反过来填充某种数据。

此外,在您的情况下,如果多个线程在 loadDictionary 调用(同步)上排队,您可能最终会多次加载相同的内容。

关于Java,没有同步的延迟初始化字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5567801/

相关文章:

java - 如果取消时 runnable 正在进行中,如何取消 ScheduledFuture 并等待 runnable 停止?

java - 无法使用 IPV6 地址向端点发送 SIP 通知

java - 通过同步方法访问的私有(private)类参数是否被视为 'synchronized object' ?

将未计算的参数传递给其他函数的 R 函数

haskell - Haskell 的 mapM 不懒吗?

java - 从 GWT 中的 flexTable 获取小部件

java - 带有 Spring Boot : static resource (i. e 的 Spring Security 4。 css, js, img) 404问题

mysql - 进行数据同步时检查已删除项目的最佳方法?

java - 嵌套同步方法的开销

lazy-evaluation - 在 Crystal 中实现惰性枚举器