java - 非线程安全单例中的部分构造对象

标签 java

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

class LazyInit
{  private static Resource resource = null;

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

最佳答案

因为乱序写入。

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

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

关于java - 非线程安全单例中的部分构造对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3966559/

相关文章:

java - Tapestry属性文件+注入(inject),实现对参数[n]的支持

java - 如何将监听 hibernate 事件的模块与实体本身分离?

Java - 在文本字段中设置 "Int"

java - 从桌面运行可执行文件给我 : *ERR* IO-21 invalid STATUS specifier for given file

java - catch 语句之前的 return 语句

java - Java同时访问同一个对象的不同成员

java - 为什么静态字段(不是final)在java的内部类中受到限制

java - Javadoc 是否具有 <![CDATA[ ... ]]> 的等价物?

java - 如何签署 Java Midlet?

java - Java if 语句什么时候退出?