在使用之前复制对局部变量的引用很重要
在OpenJDK 8中探索java.util.LinkedList的代码,我找到了以下代码。 代码很简单,但我很困惑将第一个节点的引用保存到第二行代码中的常量。 据我所知,这段代码将被内联到单行内容而无需参考复制。 我对吗? 如果是这样, 为什么需要在这个和类似的情况下复制引用 (这样的习惯用法可以在java.util.LinkedList的一半方法中找到)?
public E peek() { final Node f = first; return (f == null) ? null : f.item; }
我的第一个想法是它以某种方式帮助并发,但LinkedList不允许并发访问(除了你自己承担风险),所以我想这是优化器的一些提示,但无法弄清楚它应该如何工作。
我的第一个想法是它以某种方式帮助并发……
…所以我想这是优化者的一些提示……
都。 🙂 LinkedList
不支持并发的事实并不意味着作者不会遵循良好的做法,它告诉编译器和JIT他们应该只查看一次 。
没有f
局部变量,我们有:
public E peek() { return (this.first == null) ? null : this.first.item; }
我添加了隐含的this.
强调first
是实例字段。
因此,如果在线程A上计算this.first == null
部分,则在线程B上更改this.first.item
,当在线程A上计算this.first.item
时,它可能会抛出,因为this.first
在与此同时。 f
是不可能的,因为f
是本地的; 只有运行peek
调用的线程才会看到它。
final
一部分是良好的代码内文档(因为作者从不打算改变f
的值)和一个优化器的提示,我们永远不会改变f
,这意味着当需要优化时,它可以将它优化到其生命的一英寸内,知道它只需要读取一次。第一次 ,然后可以使用寄存器或堆栈值进行null
检查和返回。