Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在ArrayBlockingQueue中,为什么要将最终成员字段复制到局部最终变量中?_Java_Multithreading_Optimization_Final_Local Variables - Fatal编程技术网

Java 在ArrayBlockingQueue中,为什么要将最终成员字段复制到局部最终变量中?

Java 在ArrayBlockingQueue中,为什么要将最终成员字段复制到局部最终变量中?,java,multithreading,optimization,final,local-variables,Java,Multithreading,Optimization,Final,Local Variables,在ArrayBlockingQueue中,所有需要锁的方法在调用lock()之前将其复制到本地final变量 当字段this.lock为final时,是否有理由将this.lock复制到局部变量lock 此外,它还使用E[]的本地副本,然后再对其进行操作: private E extract() { final E[] items = this.items; E x = items[takeIndex]; items[takeIndex] = null; take

ArrayBlockingQueue
中,所有需要锁的方法在调用
lock()
之前将其复制到本地
final
变量

当字段
this.lock
final
时,是否有理由将
this.lock
复制到局部变量
lock

此外,它还使用
E[]
的本地副本,然后再对其进行操作:

private E extract() {
    final E[] items = this.items;
    E x = items[takeIndex];
    items[takeIndex] = null;
    takeIndex = inc(takeIndex);
    --count;
    notFull.signal();
    return x;
}

是否有理由将final字段复制到局部final变量?

这是该类作者Doug Lea喜欢使用的一种极端优化。在核心libs开发邮件列表上有一篇关于这个主题的帖子,它很好地回答了你的问题

从职位:

…复制到本地会产生最小的 字节码,对于低级代码,编写代码很好 那离机器有点近

给出了一些答案。实质上:

  • 编译器无法轻松证明方法中的final字段没有更改(由于反射/序列化等原因)
  • 大多数当前的编译器实际上没有尝试,因此每次使用最终字段时都必须重新加载该字段,这可能会导致缓存丢失或页面错误
  • 将其存储在局部变量中会强制JVM只执行一次加载

强烈强调“极端”!这不是每个人都应该仿效的通用良好编程实践。Random FYI:在其他一些情况下,当您看到这样做时,这是因为所讨论的字段是不稳定的,并且该方法需要确保它始终具有一个一致的值或引用。我认为这是“极端的”在这样的核心类中进行优化。@zamza,局部final变量仅由java编译器使用,而不是字节码(即JVM不知道局部变量是否为final)除了字节码大小之外,这也是对执行速度的优化吗?我不认为JVM必须重新加载
final
变量。如果通过反射修改
final
变量,则无法保证程序正常工作(这意味着可能不会在所有情况下都考虑新值)。
private E extract() {
    final E[] items = this.items;
    E x = items[takeIndex];
    items[takeIndex] = null;
    takeIndex = inc(takeIndex);
    --count;
    notFull.signal();
    return x;
}