编程冷知识 — 多余的局部变量final

奇怪的代码
JDK 1.8 | java.util.concurrent.locks.ReentrantLock | 125行

/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error(“Maximum lock count exceeded”);
setState(nextc);
return true;
}
return false;
}
这里第一行 :
final Thread current = Thread.currentThread();
为什么加了final, 而且还要声明一个局部变量?
探寻缘由
经过搜索, 找到的解释本质上是由于: JVM内存模型 和 OOP 之间的不同.

如果我们直接使用:
Thread current = Thread.currentThread();

函数内使用current的执行时序:

函数仅会保存current的指针
JVM会在使用current的地方, 通过指针获取Thread对象.
然后再调用相应方法. 例如: current.sleep(1L);

好像还可以接受嘛, 但如果在同一个函数内多次调用呢?程序会重复 2-3 步骤, 增加代码的性能开销.
JVM 的优化
现在JVM已经可以做到在编译期, 针对此种类型的代码调用, 将对象内联到函数的操作数栈中了. 但在JDK中还是保留了大量的final局部变量的使用, 尤其是在并发包内.
我想, 这就是老一辈工程师, 对代码的执着, 对性能的追求, 对自己的约束.

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理