在JDK1.6中,Doug在final字段前面使用next。
static final class HashEntry<K,V> {
final K key;
final int hash;
volatile V value;
final HashEntry<K,V> next;而在JDK1.7中,next字段前面是volatile。我还注意到,在JDK1.7中,get方法使用getObjectVolatile方法读取具有易失性负载语义的value字段。
我不明白Doug之前为什么使用final。如果正确性有问题,那么他如何用JDK1.7(也是JDK1.8)中的volatile替换它?
编辑:
具体来说,我的问题是,在JDK1.6的实现中,我们能用final代替volatile吗?
发布于 2015-07-15 15:08:57
关于你的第一个问题:
我不明白Doug之前为什么会使用final。如果正确性有问题,那么他如何用JDK1.7(也是JDK1.8)中的易失性来替换它呢?
这不是一个正确的问题。这两种实现在线程安全方面都是正确的。正在努力解决的是减少CHM最初的足迹。在Java6中,要使next字段成为最终结果,就需要至少使用一个位置保持器来创建对象。这导致了过多的空对象创建,因此被更改为提供需要时的创建语义。
具体来说,我的问题是,在JDK1.6的实现中,我们是否可以用易失性替换final?
当然,只要这些操作是连续一致的,它们就是这样。
Doug的一个评论涉及到这个设计上的改变
/*
* ...
* 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.
*/因此,要回答另一个可能存在的问题,为什么最初选择了final?以防止稍后的易失性读取。
发布于 2015-07-15 13:08:22
这不是用volatile代替volatile的问题。和RealSkeptic一样,它在许多其他方法中也被改变了。其目的可能是对ConcurrentHashMap.remove()进行优化。在JDK1.6中,存储桶(按哈希代码分组的对象)的列表是CopyOnWrite,因此在remove()中复制列表的一部分,在JDK1.7中只更改next指针。
https://stackoverflow.com/questions/31429918
复制相似问题