基于JDK1.8的ConcurrentHashMap分析(3)

//第一部分
final V replaceNode(Object key, V value, Object cv) {
    //先找到key的位置 hash散列
    int hash = spread(key.hashCode());
    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        //如果表为空,直接返回null
        if (tab == null || (n = tab.length) == 0 ||
            (f = tabAt(tab, i = (n - 1) & hash)) == null)
            break;
        //如果有在扩容的线程,帮助他扩容
        else if ((fh = f.hash) == MOVED)
            tab = helpTransfer(tab, f);

首先遍历整张表的桶结点,如果表还未初始化或者无法根据参数的 hash 值定位到桶结点,那么将返回 null。

如果定位到的桶结点类型是 ForwardingNode 结点,调用 helpTransfer 协助扩容。

else {
    V oldVal = null;
    boolean validated = false;
    synchronized (f) {
        if (tabAt(tab, i) == f) {
            if (fh >= 0) {
                validated = true;
                for (Node<K,V> e = f, pred = null;;) {
                    K ek;
                    if (e.hash == hash &&
                        ((ek = e.key) == key ||
                        (ek != null && key.equals(ek)))) {
                        V ev = e.val;
                        if (cv == null || cv == ev ||
                            (ev != null && cv.equals(ev))) {
                            oldVal = ev;
                            if (value != null)
                                e.val = value;
                            else if (pred != null)
                                pred.next = e.next;
                            else
                                setTabAt(tab, i, e.next);
                        }
                        break;
                    }
                    pred = e;
                    if ((e = e.next) == null)
                        break;
                }
            }
            else if (f instanceof TreeBin) {
                validated = true;
                TreeBin<K,V> t = (TreeBin<K,V>)f;
                TreeNode<K,V> r, p;
                if ((r = t.root) != null &&
                    (p = r.findTreeNode(hash, key, null)) != null) {
                    V pv = p.val;
                    if (cv == null || cv == pv ||
                        (pv != null && cv.equals(pv))) {
                        oldVal = pv;
                        if (value != null)
                            p.val = value;
                        else if (t.removeTreeNode(p))
                            setTabAt(tab, i, untreeify(t.first));
                    }
                }
            }
        }
    }
    if (validated) {
        if (oldVal != null) {
            if (value == null)
                addCount(-1L, -1);
            return oldVal;
        }
        break;
    }
}

代码很多,但我觉得思路不难。就是找到那个桶以后,直接加锁。判断是链表还是树,然后删除即可。

(三)get方法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e62e23a51fd49c42e74de7db91be3647.html