我阅读了关于 ConcurrentHashMap 的 JDK 源代码。
但是下面的代码让我很困惑:
public boolean isEmpty() {
final Segment<K,V>[] segments = this.segments;
...
}
我的问题是:
“this.segments”被声明:
final Segment<K,V>[] segments;
所以,在这里,在方法的开头,声明了一个相同类型的引用,指向相同的内存。
作者为什么要这样写?他们为什么不直接使用 this.segments 呢?有什么原因吗?
最佳答案
这是涉及 volatile
变量的无锁代码的典型习语。在第一行,您阅读了 volatile
一次,然后使用它。与此同时,另一个线程可以更新 volatile
,但您只对最初读取的值感兴趣。
此外,即使所讨论的成员变量不是 volatile 而是 final,这个习惯用法也与 CPU 缓存有关,因为从堆栈位置读取比从随机堆位置读取对缓存更友好。本地 var 最终绑定(bind)到 CPU 寄存器的可能性也更高。
对于后一种情况,实际上存在一些争议,因为 JIT 编译器通常会处理这些问题,但 Doug Lea 是坚持一般原则的人之一。
关于java - 为什么JDK源代码取 `final`实例的 `volatile`副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13155860/