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

Vla*_*nko 12 java

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

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

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

T.J*_*der 12

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

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

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

没有f局部变量,我们有:

public E peek() {
    return (this.first == null) ? null : this.first.item;
}
Run Code Online (Sandbox Code Playgroud)

我添加了暗示this.强调这first是一个实例字段.

因此,如果this.first == null在线程A上评估该部分,则this.first在线程B this.first.item上进行更改,当在线程A上进行评估时,它可能会抛出,因为它this.first已经null同时发生.这是不可能的f,因为f是本地的; 只有运行peek调用的线程才会看到它.

final部分既是良好的代码内文档(因为作者从不打算改变它的价值f),也提示优化器我们永远不会改变f,这意味着当需要优化时,它可以优化它知道它只需读取this.first 一次就可以使用寄存器或堆栈值进行null检查和返回.

  • 那么,你是说OP的建议是JIT会将f内联到f.这是错误的. (2认同)