用于访问volatile实例变量的局部变量

时间:2013-02-02 21:01:27

标签: java oop design-patterns volatile

创建对已保存为成员字段的静态volatile变量的本地引用的目的或价值是什么。此处的代码来自java.util.Scanner JDK 6b14 here

class Scanner {
    private static volatile Pattern linePattern;
    ...
    private static Pattern linePattern() {
        Pattern lp = linePattern;
        if (lp == null)
            linePattern = lp = Pattern.compile("...");
        return lp;
    }
    ...
}

The Java Tutorials:“对于声明为volatile的所有变量(包括长变量和双变量),读取和写入都是原子的...对volatile变量的任何写入都会建立与之后读取同一变量的先发生关系。 “

这意味着读取Pattern对象的引用不会中途失败,因为它已经更改。 volatile关键字应该保护这些类型的访问,所以我不会复制局部变量来确保返回有效值。

此外,可以在成员字段上完成延迟初始化,而无需中间局部变量:

if (linePattern == null) linePattern = Pattern.compile("...");

看起来是herehere的字节码优化。使用局部变量产生较小的字节码(较少的指令)以及较少的实际值访问(这是一个昂贵的易失性读取)。然而,他们没有使用最终的变量优化,所以我对得出这个结论持怀疑态度。

4 个答案:

答案 0 :(得分:2)

Lazy initialization,即推迟工作,直到确实有必要为止。

答案 1 :(得分:1)

它保证返回的值不为NULL - 即使在检查和返回之间将静态变量设置为NULL。

同时,如果需要,它是一个不同步的延迟初始化,重新初始化;)。

答案 2 :(得分:1)

这个“速度”起来了。访问volatile变量非常昂贵。使用可以通过将其分配给堆栈变量并使用

访问它来消除此开销

答案 3 :(得分:0)

对于volatile字段,linePattern可能会在不同的行之间发生变化。将引用复制到局部变量可确保您不会出现不一致的状态。例如,如果你写了

 if (linePattern == null)
    linePattern = Pattern.compile("...");

然后linePattern可能在Pattern.compile执行时已停止为空。