2010-10-19 75 views
5

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

class LazyInit 
{ private static Resource resource = null; 

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

查看https://secure.wikimedia.org/wikipedia/en/wiki/Double-checked_locking – Bozho 2010-10-19 08:38:28

回答

7

由于乱序写入。

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

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