双重检查模式(DCL)问题

09-12-23 myserver368
         

本来在上篇帖子里发了,不过没人回答,呵呵 做一个新的问题,问问大家怎么看。

effective java中文版一书中,在165页里说:

迟延初始化(lazy initialization)的双重检查模式(DCL):

private static Foo foo=null;

public static Foo getFoo(){

if(foo == null){

synchronized (Foo.class){

if(foo==null)

foo=new Foo();

}

}

return foo;

}

如果一个线程在不使用同步的情况下读入该引用,并调用被引用的对象上的方法,那么这个方法可能会看到对象被部分初始化的状态,从而导致灾难性的后果。

         

myserver368
2009-12-23 11:33

下面说道

一个线程看到一个被迟缓构建的对象处于部分初始化的状态,这种情形并不直观。在将引用发布到一个域(foo,其他的线程将从这个域读取它的值)中之前,对象应该被完整地构造出来,但是,在缺少同步的情况下,读入一个已“发布”的对象引用并不保证:一个线程将会看到在对象引用发布之前所有保存在内存中的数据。特别是,读入一个已发布的对象引用并不保证:读线程将会看到被引用的对象内部的最新数据值。一般情况下,双重检查模式并不能正确地工作,但是如果被共享的变量包含一个原语值,而不是一个对象引用,则它可以正常的工作[pugh01b].

我在《深入浅出设计模式(中文版)》第五章182页看到 对java5

用volatile修饰符可以解决这个问题。

请问大师能不能做个测试程序让我辈看看阿!

banq
2009-12-23 12:02

测试案例:

Breaking the Singleton

根本解决方法是做一个内部单例类:

private static class ElvisHolder {
static final Elvis INSTANCE = new Elvis();
}
static Elvis getInstance() {
return ElvisHolder.INSTANCE;
}
<p>

一个供参考的PPT:http://www.slideshare.net/ouertani/singleton-sum-2204910?src=embed

myserver368
2009-12-23 12:12

google 的blogspot 被封了 打不开这个连接。

myserver368
2009-12-23 14:43

看了banq给我的资料 万分感谢,但是有几个问题。

一, yohan 的这种生成类的方法 其实是破坏了原来类的构造器的私有属性,看下代码:

Singleton s = Singleton.getInstance();

Class<?> clazz = Singleton.class;

Constructor<?> cons = clazz.getDeclaredConstructor();

cons.setAccessible(true);

Singleton s2 = (Singleton) cons.newInstance ();

文章里说 这个是由于java类的生成 如果有两个load()的话,对同一个类 他们认为是不同的类,所以生成了两遍。可上面的代码哪里有两个load 呢?难道这个newInstance() 就是一个新的load吗?

这个可以说是一个黑客的做法 正常的程序里不应该有这样用的,是这样吗?请大师指点。

二。 用内部类确实可以解决这个问题,可为什么内部类可以解决这个问题?假设一的问题成立,则用内部类 也是有两个load() 这样也是会作为不同的类对待,应该不能避免阿,大师能解释一下吗?

2Go 1 2 下一页