0

创建对已作为成员字段保存的静态 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;
    }
    ...
}

Java 教程:“对于声明为 volatile 的所有变量(包括 long 和 double 变量),读取和写入都是原子的……对 volatile 变量的任何写入都会与随后读取同一变量建立起先发生关系。”

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

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

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

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

4

4 回答 4

2

延迟初始化,即延迟工作直到真正需要。

于 2013-02-02T21:04:05.850 回答
1

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

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

于 2013-02-02T21:13:32.363 回答
1

这“加速”了事情。访问volatile变量的成本很高。使用可以通过将其分配给堆栈变量并访问它来避免这种开销

于 2013-02-02T22:50:13.267 回答
0

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

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

thenlinePattern可能在执行时不再为空Pattern.compile

于 2013-02-02T21:05:04.150 回答