在JDK 1.6和JDK 1.7中ConcurrentHashMap的不同`next`条目

cha*_* ro 8 java concurrency hashmap concurrenthashmap java.util.concurrent

在JDK 1.6中,Doug Lea final在该next领域之前使用.

static final class HashEntry<K,V> {
    final K key;
    final int hash;
    volatile V value;
    final HashEntry<K,V> next;
Run Code Online (Sandbox Code Playgroud)

而在JDK 1.7中,next字段前面是volatile.我还注意到在JDK 1.7中,该get方法采用getObjectVolatile读取value字段的方法,该字段具有易失性加载语义.

我不知道Doug Lea之前使用过什么final.如果正确性存在问题,那么如何volatile在JDK 1.7(也是JDK 1.8)中替换它?

编辑:

具体来说,我的问题是我们可以final用volatileJDK 1.6的实现代替吗?

Joh*_*int 2

对于你的第一个问题:

我不明白为什么 Doug Lea 以前使用 Final。如果正确性有问题的话,那么他怎么可能在JDK 1.7(还有JDK 1.8)中将其替换为 volatile 呢?

这不是正确与否的问题。就线程安全而言,两种实现都是正确的。试图解决的问题是减少 CHM 的初始足迹。在 Java 6 中,将next字段设为 Final 需要创建至少带有占位符的对象。这导致了过多的空对象创建,因此进行了更改以提供“需要时创建”语义。

具体来说,我的问题是,我们可以在 JDK 1.6 的实现中将 Final 替换为 volatile 吗?

当然,只要操作继续保持顺序一致(它们确实如此)。


Doug Lea 的评论之一涉及到这一设计变更

 /* 
 * ...
 * Historical note: The previous version of this class relied
 * heavily on "final" fields, which avoided some volatile reads at
 * the expense of a large initial footprint.  Some remnants of
 * that design (including forced construction of segment 0) exist
 * to ensure serialization compatibility. 
 */
Run Code Online (Sandbox Code Playgroud)

那么,回答您可能会遇到的另一个问题,为什么final最初选择它?为了防止稍后出现一些不稳定的读取。