【问题标题】:Temporary nodes in ConcurrentHashMap Java 8ConcurrentHashMap Java 8 中的临时节点
【发布时间】:2017-10-19 12:56:20
【问题描述】:

查看java.util.ConcurrentHashMap.putVal(),我遇到了一些检查数组中是否有任何对象(节点)具有hashcode() 作为-ve 值的条件。这段代码,例如:

    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        if (tab == null || (n = tab.length) == 0)
            tab = initTable();
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            if (casTabAt(tab, i, null,
                         new Node<K,V>(hash, key, value, null)))
                break;                   // no lock when adding to empty bin
        }
        else if ((fh = f.hash) == MOVED) // THIS HERE???
            tab = helpTransfer(tab, f);

请注意,它检查fh==MOVEDMOVED 是否为-1,那么CHM 中哪些对象(节点)的hashcode() 为负数?

进一步阅读文档,它说除了真实节点之外,可能存在 3 种类型的节点(bin 中的第一个),它们的 hashcode() 可能在:

    static final int MOVED     = -1; // hash for forwarding nodes
    static final int TREEBIN   = -2; // hash for roots of trees
    static final int RESERVED  = -3; // hash for transient reservations

我可以理解首先是在调整地图大小时作为临时参考,但我似乎无法理解 -2 和 -3 hashcode() 的用法。帮忙?

【问题讨论】:

    标签: java hashmap java.util.concurrent


    【解决方案1】:

    TREEBIN 用于标记TreeBinRESERVED 标记ReservationNode 用于computecomputeIfAbsent 方法。这些哈希码可用于确定 bin 节点的类型。

    bin节点有4种,Node为hash &gt;= 0,TreeBin为hash == TREEBIN,ForwardingNode为hash == MOVED,ReservationNode为hash == RESERVED

    这些具有不同哈希码的节点用于避免并发问题。虽然我们可以使用instanceof 来区分它们,但将Node 与其他区分更有效,因为它们都是Node 的子类。考虑到效率,这种哈希码设计很有用。

    此外,创建这些类型还有其他原因。例如,与HashMap相比,使用TreeBin后,我们不需要moveRootToFront(在其他线程查找时会导致问题),因为TreeBin存储了树的根。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-05
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 2017-03-30
      • 1970-01-01
      • 2015-08-23
      • 2020-10-30
      相关资源
      最近更新 更多