在DCL的情况下需要volatile关键字

sdi*_*ver 2 java concurrency multithreading volatile

我只是在实践中阅读并发性.我开始知道有必要在双重检查锁定机制中使用volatile关键字,否则线程可以读取非空对象的失效值.因为它可以在不使用volatile关键字的情况下重新排序指令.由于该对象引用可以在调用构造函数之前分配给资源变量.所以线程可以看到部分构造的对象.

我有一个问题.

我假设synchronized块也限制编译器从指令重新排序,那么为什么我们需要volatile关键字呢?

public class DoubleCheckedLocking {
    private static volatile Resource resource;
    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null)
                    resource = new Resource();
            }
        }
        return resource;
    }
}
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 6

如果调用线程(T1)也从同步块(在同一个锁上)读取它,则JMM仅保证线程T1将看到由同步块内的另一个线程T2创建的正确初始化对象.

由于T1可以看到资源不为空,因此在不经过同步块的情况下立即返回它,它可以获得一个对象但是看不到它的状态正确初始化.

使用volatile会带来这种保证,因为在写入易失性字段和读取该易失性字段之间存在先发生的关系.