实践中的java并发16.7

时间:2012-09-15 15:33:00

标签: java multithreading concurrency

此代码用于演示双重检查锁定反模式:

@NotThreadSafe
public class DoubleCheckedLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null)
                    resource = new Resource();
            }
        }
        return resource;
    }
}

我可以通过将其修改为:

来避免此问题
@NotThreadSafe
public class DoubleCheckedLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null){
                    Resource r=new Resource();
                    resource = r;
                }
            }
        }
        return resource;
    }
}

据我所知,

Resource r=new Resource();
resource = r;

该编译器应为此提供事先发生的关系。

3 个答案:

答案 0 :(得分:4)

据我所知,双重检查锁定模式的唯一已知实现(对于JDK5及更高版本)使用'volatile'关键字。 See Fixing Double-Checked Locking using Volatile

答案 1 :(得分:2)

public static Resource getInstance() {
    if (resource == null) {
        synchronized (DoubleCheckedLocking.class) {
            if (resource == null){
                Resource r=new Resource();
                resource = r;
            }
        }
    }
    return resource;
}

保证线程之间正确可见性的唯一方法是通过同步(通过synchronizedvolatile,...)创建同步与关系。

如果您没有 synchronize-with 关系,则不需要线程来查看其他线程的修改。

在这种情况下,线程可以创建Resource并在resource中存储对它的引用。然后第二个帖子可能会输入getInstance(),并看resource != null。第二个线程不能保证看到resource构造的所有效果,因为它不是第一个线程同步。

答案 2 :(得分:2)

允许编译器进行优化:

Resource r=new Resource();
resource = r;

resource=new Resource();

所以你的调整无效。