java8中并发HashMap中的sizectl

时间:2018-08-26 12:24:39

标签: java concurrency concurrenthashmap

由于我正在用java8阅读并发HashMap的源代码,因此我对sizeCtl变量有些困惑,它说

  

为负数时,表正在初始化或调整大小:-1用于初始化,否则-(1 +活动的调整大小线程数)

但是在源代码中,当尝试调整U.compareAndSetInt(this, SIZECTL, sc, sc + 1)的大小时将使用ConcurrentHashMap,并在完成操作后使用U.compareAndSetInt(this, SIZECTL, sc = sizeCtl, sc - 1)

这些操作使我感到困惑,例如,如果同时有2个线程调整映射大小,则sizeCtl-3,但是,当有新线程尝试帮助调整大小时,根据以上注释的描述,sizeCtl应该为-4,但根据代码-2似乎应该为U.compareAndSetInt(this, SIZECTL, sc, sc + 1)

final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {
    Node<K,V>[] nextTab; int sc;
    if (tab != null && (f instanceof ForwardingNode) &&
        (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
        int rs = resizeStamp(tab.length);
        while (nextTab == nextTable && table == tab &&
               (sc = sizeCtl) < 0) {
            if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
                sc == rs + MAX_RESIZERS || transferIndex <= 0)
                break;
            if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
                transfer(tab, nextTab);
                break;
            }
        }
        return nextTab;
    }
    return table;
}

1 个答案:

答案 0 :(得分:0)

我认为它说错了。

  

为负数时,表正在初始化或调整大小:-1用于初始化,否则-(1 +活动的调整大小线程数)

由于第一个进入函数transfer的线程将sizeCtl设置为(resizeStamp(tab.length) << RESIZE_STAMP_SHIFT) + 2。这是一个负数,其绝对值非常大。当每个线程进入该函数时,sizeCtl递增1,然后在每个线程退出该函数之前减1。

while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
               (n = tab.length) < MAXIMUM_CAPACITY) {
            int rs = resizeStamp(n);
            if (sc < 0) {
                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
                    sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
                    transferIndex <= 0)
                    break;
                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
                    transfer(tab, nt);
            }
            else if (U.compareAndSwapInt(this, SIZECTL, sc,
                                         (rs << RESIZE_STAMP_SHIFT) + 2))
                transfer(tab, null);
            s = sumCount();
        }

这些是我的想法,但我不确定。