在使用之前复制对局部变量的引用很重要

时间:2016-06-12 15:49:21

标签: java

在OpenJDK 8中探索java.util.LinkedList的代码,我找到了以下代码。代码很简单,但我对将第一个节点的引用保存到第二行代码中的常量感到困惑。据我所知,这段代码将被内联到单行内容而无需参考复制。我对吗?如果是这样,为什么需要在此类似情况下复制引用(这种习惯用法可以在java.util.LinkedList的一半方法中找到)?

public E peek() {
    final Node<E> f = first;
    return (f == null) ? null : f.item;
}

我的第一个想法是它以某种方式帮助并发,但LinkedList不允许并发访问(除了你自己承担风险),所以我想这是优化器的一些提示,但无法弄清楚它是如何实现的应该工作。

1 个答案:

答案 0 :(得分:12)

  

我的第一个想法是它以某种方式帮助并发...

     

...所以我想这是优化者的一些暗示......

两者。 :-) LinkedList不支持并发的事实并不意味着作者不会遵循良好的做法,它告诉编译器和JIT它们应该只查找{{1 } 一次

如果没有first局部变量,我们就会:

f

我添加了隐含的public E peek() { return (this.first == null) ? null : this.first.item; } 以强调this.是一个实例字段。

因此,如果在线程A上评估first部分,则在线程B上更改this.first == null,当在线程A上评估this.first时,它可能因为{{1}而抛出在此期间已成为this.first.itemthis.first这是不可能的,因为null是本地的;只有运行f调用的线程才会看到它。

f部分既是良好的代码内文档(因为作者从不打算更改peek的值),也是优化器的提示,我们永远不会改变final 1}},这意味着当需要进行优化时,它可以将其优化到其生命的一英寸范围内,因为它知道它只需要阅读f 一次然后可以使用f检查和返回的寄存器或堆栈值。