在ArrayBlockingQueue中,为什么要将最终成员字段复制到本地最终variables?

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

 public boolean offer(E e) { if (e == null) throw new NullPointerException(); final ReentrantLock lock = this.lock; lock.lock(); try { if (count == items.length) return false; else { insert(e); return true; } } finally { lock.unlock(); } } 

当字段this.lockfinal时候,是否有任何理由将this.lock复制到局部variableslock final

此外,它还在使用E[]之前使用本地副本:

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

是否有任何理由将最终字段复制到本地最终variables?

这是该课程的作者Doug Lea喜欢使用的极端优化。 下面是core-libs-dev邮件列表上关于这个确切的主题的最近的一个post,它很好地回答了你的问题。

从post:

…复制到本地生成最小的字节码,对于低级代码,编写代码更接近机器

这个线程给出了一些答案。 实质上:

  • 编译器不能轻易地certificate最终字段在方法内不会改变(由于reflection/序列化等)
  • 大多数当前的编译器实际上不会尝试,因此每次使用时都必须重新加载最终字段,这可能导致caching未命中或页面错误
  • 将其存储在本地variables中会强制JVM仅执行一次加载