我在Java中看到了一些示例,它们在代码块上进行同步以更改某些变量,而该变量最初被声明为volatile。那初始化了那个实例……我的问题是为什么我们在同步它的同时声明它为volatile,为什么我们需要同时做这两个?它们中的一个不足以满足另一个需求吗?

public class SomeClass {
    volatile static Object uniqueInstance = null;

    public static Object getInstance() {
        if (uniqueInstance == null) {
            synchronized (someClass.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new SomeClass();
                }
            }
        }
        return uniqueInstance;
    }
}
提前致谢。

最佳答案

如果第一个检查在同步块(synchronized block)内,则在这种情况下,仅通过同步本身就足够了(但是不是这样,并且如果变量不是易变的,则一个线程可能看不到另一个线程执行的更改)。仅凭挥发就不够,因为您需要原子地执行多个操作。但是要当心!您在这里拥有的是所谓的双重检查锁定-一种常见的习惯用法,不幸的是does not work reliably。我认为自Java 1.6以来,这种情况已经发生了变化,但是这种代码仍然有风险。

编辑:当变量是volatile时,此代码自JDK 5起就可以正常工作(不是我之前写的6),但是在JDK 1.4或更早版本下将无法正常工作。

10-05 21:39