ArrayBlockingQueue
中,所有需要锁定的方法在调用final
之前将其复制到本地lock()
变量。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.lock
为lock
时,是否有理由将this.lock
复制到本地变量final
? br />另外,在执行操作之前,它还会使用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变量?
#1 楼
该类的作者Doug Lea喜欢使用这种极端的优化方法。这是有关core-libs-dev邮件列表的最新主题的相关帖子,可以很好地回答您的问题。来自帖子:
...复制到本地会产生最小的
字节码,对于低级代码,最好编写与计算机更近的代码
#2 楼
该线程给出了一些答案。本质上:编译器不能轻易证明方法中的final字段不变(由于反射/序列化等)。
当前大多数编译器实际上并没有这样做不要尝试,因此每次使用时都必须重新加载最终字段,这可能导致高速缓存未命中或页面错误
将其存储在局部变量中会强制JVM仅执行一次加载
评论
我认为JVM不必重新加载最终变量。如果通过反射修改了最终变量,则无法保证程序正常运行(这意味着在所有情况下都可能不会考虑新值)。
–icza
2014年10月1日下午6:35
评论
强烈强调“极端”!这不是每个人都应该模仿的通用的良好编程习惯。
– Kevin Bourrillion
2010年5月7日13:42
随机FYI:在其他情况下,当您看到此操作完成时,这是因为所讨论的字段是易变的,并且该方法需要确保它始终具有单个一致的值或参考。
– Kevin Bourrillion
2010年5月7日13:44
我将在这样的核心类中进行这种“极端”优化。
–埃里克·罗伯逊(Erick Robertson)
2011年1月13日12:58
@zamza,局部最终变量仅由Java编译器使用,而不由字节码使用(即JVM不知道局部变量是否为最终变量)
– bestsss
2011年11月6日,下午1:32
除了字节码大小之外,这是否还优化了执行速度?
– SantiBailors
17年2月9日在9:08