【问题标题】:Partially constructed objects in non thread-safe Singleton非线程安全单例中的部分构造对象
【发布时间】:2010-10-19 16:54:52
【问题描述】:

在多线程环境中,线程怎么可能看到“部分构造的对象”?我知道它不是线程安全的,因为多个线程可以创建多个实例。

class LazyInit
{  private static Resource resource = null;

    public static getInstance()
    {  if (resource == null) { resource = new Resource();  }
       return instance;
    }
}

【问题讨论】:

标签: java


【解决方案1】:

因为乱序写入。

如果您的构造函数写入非最终成员,它们不必立即提交到内存,实际上它们甚至可以在单例变量之后提交。 Java 保证影响它的线程按顺序看到影响,但除非您设置内存屏障,否则其他线程不会看到影响。
有关详细信息,请参阅 Java 规范的 this questionthis page

这可能不是重点,但在您的示例中,两个线程完全有可能看到不同的单例。假设一个线程测试变量的无效性,进入if 并在它有机会构造对象之前被抢占。获取 CPU 的新线程现在测试尚未为空的对象,构造单例。当旧线程再次开始运行时,它会愉快地完成对象的构造并覆盖单例变量。
如果 Resource 的构造函数调用一个最终会导致另一个调用此 getInstance 的方法,则会出现另一个更可怕的问题。即使程序的状态不会导致无限循环,您也会创建多个单例实例。

【讨论】:

    猜你喜欢
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 2013-07-27
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    相关资源
    最近更新 更多