非线程安全的Singleton中部分构造的对象

时间:2010-10-19 08:36:46

标签: java

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

class LazyInit
{  private static Resource resource = null;

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

1 个答案:

答案 0 :(得分:7)

由于无序写入。

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

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