繁体   English   中英

初始化静态变量时使用局部变量

[英]Using a local variable when initializing a static variable

java.util.Scanner的源代码java.util.Scanner我发现了这些静态实用程序方法:

private static Pattern separatorPattern() {
    Pattern sp = separatorPattern;
    if (sp == null)
        separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
    return sp;
}

private static Pattern linePattern() {
    Pattern lp = linePattern;
    if (lp == null)
        linePattern = lp = Pattern.compile(LINE_PATTERN);
    return lp;
}

为什么它以如此复杂的方式完成而不仅仅是,比方说,

private static Pattern linePattern() {
    if (linePattern == null)
        linePattern = Pattern.compile(LINE_PATTERN);
    return linePattern;
}

在这里使用局部变量( lp )有什么意义? 这是某种优化技术吗? 或者可能是针对并发修改的预防措施? 但是linePattern不能再次设置为null ,因为此方法是修改它的唯一位置。

我相信所有关于与linePatternseparatorPattern字段一起使用的volatile关键字

private static volatile Pattern separatorPattern;
private static volatile Pattern linePattern;

由于规格

Java编程语言允许线程访问共享变量(第17.1节)。 通常,为了确保共享变量一致且可靠地更新,线程应确保通过获取锁定来独占使用此类变量,该锁定通常会对这些共享变量实施互斥。

Java编程语言提供了第二种机制,即volatile字段,比某些用途的锁定更方便。

字段可以声明为volatile,在这种情况下,Java Memory Model可确保所有线程都看到变量的一致值

我们也可以在这里阅读

声明一个易变的Java变量意味着:

  • 这个变量的值永远不会被线程本地缓存:所有读写都将直接进入“主存”;

  • 对变量的访问就像包含在同步块中一样,自身同步。

这就是为什么他们首先尝试直接读取字段的值然后用新值覆盖它

我认为他们希望避免两次从volatile场中读取。

  • 一次检查是否为null
  • 一次return

在他们的版本中,他们只是

  • 一旦将其读入局部变量
  • 确认局部变量不为null
  • 返回该局部变量

优化是针对“快乐路径”,其发生频率比“初始设置路径”更频繁地发生,其仅发生一次 - 或者如果在完成初始化之前同时调用该方法,则最多几次。

或者可能是针对并发修改的预防措施?

没有这样的预防措施。 如果在设置静态volatile字段之前同时调用linePattern ,则会多次创建模式(但没关系),将返回不同的实例,并选择随机的实例(这也很好,因为它们是等价的)。

任何防范这种情况的措施只会增加我们“快乐路径”的成本,所以只有在实例因某种原因必须真正成为单身人士的情况下才应该这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM