java - 为什么JDK源代码取 `final`实例的 `volatile`副本

标签 java

我阅读了关于 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/

相关文章:

java - 反复更新Java中的字符串

java - Apache ftp.retrieveFileStream 返回 null

java - Applet 中的 Paint() 方法内的无限循环不允许我与显示的按钮进行交互

java - 代理 servlet 和 iframe 从另一个域运行站点

java - CopyOnWriteArrayList 如何是线程安全的?

java - java中如何使某些行的开头和结尾不同

java - JSP通过ajax发送Java变量

java - 使用 Jackson 数据格式 XML 将 XML 转换为 Java 对象

Java : How to add date in to mysql database and get back

java - 在 Android 中以编程方式将 TextView 置于 ConstraintLayout 中心 (java)