java - 具有同步块(synchronized block)的 Java 内存模型中单例的弱点

标签 java multithreading singleton data-synchronization java-memory-model

我正在阅读 Nir ​​Shavit 的《多处理器计算的艺术》。它解释了 Java 内存模型并在第 62 页给出了示例:

public static Singleton getInstance() {
  if (instance == null) {
    synchronized(Singleton.class) {
      if (instance == null)
      instance = new Singleton();
    }
  }
  return instance;
}

并说:

This pattern, once common, is incorrect. At Line 5, the constructor call appears to take place before the instance field is assigned, but the Java memory model allows these steps to occur out of order, effectively making a partially initialized Singleton object visible to other programs.

那么,这是否意味着这种同步可能无法保证我们想要从 Singleton 获得的东西?

最佳答案

So, does it mean that such kind of synchronization may not guarantee what we want from Singleton?

这取决于你想从单例那里得到什么。如果您只想要一个实例,代码片段中的解决方案将实现这一目标。如果您只需要一个实例并且希望在访问该实例时完美初始化该实例(这个要求是否太多?),那么,不,您将无法通过该代码片段实现这一目标。

另一个线程调用 getInstance 并读取 instance 字段的值

if (instance == null) {

可能会看到引用尚未由 Controller 初始化的对象的指定值。由于该值不是 null,因此该方法会返回该值,并且未初始化的对象会泄漏。

通过将该字段标记为 volatile 可以解决此问题。

关于java - 具有同步块(synchronized block)的 Java 内存模型中单例的弱点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29187165/

相关文章:

java - C# 到 java 的交叉编译器有哪些限制和优点?

java - 在 Java 企业应用程序中使用翻译 map 时,如何获得良好的编码风格和易于维护?

c - 并行二分查找的性能比串行版本差

java - 为什么不建议同步方法?

c - 事件未使用 ResetEvent() 重置

java - 线程池连接 vs 单例设计模式获取单个数据库连接

java - Itext - 如何使用 acrofields 克隆页面?

c# - 使用 FakeItEasy 伪造单例

c# - 通用单例

java - Android 自定义 ListView 与 ImageButton