我们真的需要在本地复制 this.myVolatile 来执行 Java 8 中的同步 double if 模式吗?

Do we really need to copy this.myVolatile locally to do the synchronization double if pattern in Java 8?

更改现有代码是否对我们有任何好处:

class MyClass {
    volatile Object myVariable;
    Object myMethod() {
        if (myVariable == null) {
            synchronized(this) {
                if (myVariable == null) {
                    myVariable = this.getNewValue();
                }
            }
        }
        return myVariable;
    }
}

class MyClass {
    volatile Object myVariable;
    Object myMethod() {
        Object tmp = this.myVariable;
        if (tmp == null) {
            synchronized(this) {
                tmp = this.myVariable;
                if (tmp == null) {
                    this.myVariable = tmp = this.getNewValue();
                }
            }   
        }
        return tmp;
    }
}

我看不出在使用之前在本地复制 this.myVariable 有什么意义,而且我认为对每个 class 变量使用 "this." 不是一个好习惯。

复制到局部变量更有效也更正确。

更高效:假设在一般情况下,myVariable 是 non-null。在第一个版本中,您 两次 读取 myVariable,一次检查空值,一次检查 return 值。在第二个版本中,您读取 myVariable 一次,读取 tmp 两次(局部变量访问,这是微不足道的)。使用 volatile 的全部意义在于强大的内存保证,这些保证意味着两次读取是 non-trivial 一次读取的性能损失。

更正确:假设 myVariable 是某种需要定期刷新的 "cache"。 IE。有一个后台线程定期将 myVariable 设置为 null 以便在下次读取时重新加载。在第一个版本中,您 两次 单独读取 myVariable。第一次读取可能 return 非 null,然后 "cache refresh" 逻辑运行并将 myVariable 设置为 null。第二次读取(到return值)然后returns null!在第二个版本中,tmp 总是 您为 null 测试的值(假设 getNewValue() 从不 returns null当然)。

请注意,在此代码中使用 "this." 是一种风格选择,与正确性或性能问题无关。

这在很大程度上只是对 https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java 中所述内容的扩展。