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

7次阅读

共计 940 个字符,预计需要花费 3 分钟才能阅读完成。

奇怪的代码
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 局部变量的使用, 尤其是在并发包内.
我想, 这就是老一辈工程师, 对代码的执着, 对性能的追求, 对自己的约束.

正文完
 0