heima并发31---ConcurrentHashMap--274(150-158)

两个用途:1.代表处理完的,不会有其他的操作了,加上这个绿色的块块就是forwardingNode。

2.表示去新的列表找数据去get

volatile就是配合cas保证线程安全的。

两个作用,一个是代表链表处理完毕,一个是去新的链表找。

-------------------------------------------------------------------------------------------------------------------

链表比较长就是从o(1)到o(n)。

用红黑树替换下。

链表为8,先尝试扩容,到数组扩容64以后,变为红黑树,6变回来

---150---

源码分析:

三个参数,初始容量,负载因子,并发度。

如果初始容量小于并发度就改为并发度。

实现的是懒惰的初始化,第一次用的时候才会初始化的。

 计算8的话就是16。必须是2的n方。

设置为8,0.75是扩容的阈值。

创建的话就是16。

---151---

get方法,get是全程不加锁的:

get的全程不加锁的。

看下tabAt方法:

按照位与就是取模。

node创建好了就有自己的hash了。

---

get的时候必须是key和equals都一样的。

---

看下:

调用find方法去新的table找key。

---

---

---152---

put流程:

---

true不会覆盖旧值。

---

spread函数可以保证有很好的hash性质,并且保证为正数。

---

concurrentHashMap不允许有空的键值对,不准有空的键值。是null会抛出异常的。

---

懒惰初始化,创建完成进入下一个循环去put。

---

头结点是空的我占位。

---

看下头节点是不是在进行扩容。是的话我就去帮忙扩容的。

---153---

进入就不是扩容也不是初始化了,并且桶下标被占位冲突了。只有在这里加锁了。

只有在桶下标冲突的话才会加锁。

锁的是这个桶的链表的头结点。

1.看下链表的头节点有没有被移动过。

2.头节点的hash码都是大于0的。红黑树或者ForwardingNode是小于0的。

3.普通节点就是下面的逻辑

4.红黑树

5.尝试把链表转化为红黑树 binCount代表链表的长度 先扩容大于64链表的长度还是大于8才会扩容

6.这个类似于LongAddr的逻辑.,提高并发度。

---154---

看下这个方法:懒惰初始化只能让一个线程把hash表创建出来的

我创建其他的线程就不能创建了。

sizeCtl为-1就是正在创建hash表

其他线程cas失败了 会进入下一个循环的

sc代表下次扩容的阈值

---155---

addCount方法:

第一个参数是1第二个参数是链表的长度。类似LongAddr的思想设置累加单元,增加并发度。

参数1是计数值1  参数2是链表的长度

1.没有累加单数组或者是没有累加单元。

第一次cas累加失败

2.是不是需要扩容:https://blog.csdn.net/jupiter_888/article/details/103852735

check是链表的长度 sizeCtl是扩容的阈值

3.这里改为负数进行扩容。

4.扩容。

5.其他的线程cas扩容失败,帮忙扩容。

---156---

size流程

SIZE的获得是不准确的,是大概值。

---157---

看下扩容的流程:

// 原始的table 新的table
private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {
        int n = tab.length, stride;
        if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)
            stride = MIN_TRANSFER_STRIDE; // subdivide range
        if (nextTab == null) {            // initiating
            try {
                @SuppressWarnings("unchecked")
                 // 1.创建新的
                Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];
                nextTab = nt;
            } catch (Throwable ex) {      // try to cope with OOME
                sizeCtl = Integer.MAX_VALUE;
                return;
            }
            nextTable = nextTab;
            transferIndex = n;
        }
        int nextn = nextTab.length;
        // 2.处理完替换为这个
        ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
        boolean advance = true;
        boolean finishing = false; // to ensure sweep before committing nextTab
        // 节点搬迁 以链表为单位移动
        for (int i = 0, bound = 0;;) {
            Node<K,V> f; int fh;
            while (advance) {
                int nextIndex, nextBound;
                if (--i >= bound || finishing)
                    advance = false;
                else if ((nextIndex = transferIndex) <= 0) {
                    i = -1;
                    advance = false;
                }
                else if (U.compareAndSwapInt
                         (this, TRANSFERINDEX, nextIndex,
                          nextBound = (nextIndex > stride ?
                                       nextIndex - stride : 0))) {
                    bound = nextBound;
                    i = nextIndex - 1;
                    advance = false;
                }
            }
            if (i < 0 || i >= n || i + n >= nextn) {
                int sc;
                if (finishing) {
                    nextTable = null;
                    table = nextTab;
                    sizeCtl = (n << 1) - (n >>> 1);
                    return;
                }
                if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
                    if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
                        return;
                    finishing = advance = true;
                    i = n; // recheck before commit
                }
            }
            // 链表头处理完了 会替换为fwd
            else if ((f = tabAt(tab, i)) == null)
                advance = casTabAt(tab, i, null, fwd);
            // 已经是了 处理下一个链表
            else if ((fh = f.hash) == MOVED)
                advance = true; // already processed
            else {
                // 链表头有元素的锁住
                synchronized (f) {
                    if (tabAt(tab, i) == f) {
                        Node<K,V> ln, hn;
                        if (fh >= 0) {
                            int runBit = fh & n;
                            Node<K,V> lastRun = f;
                            for (Node<K,V> p = f.next; p != null; p = p.next) {
                                int b = p.hash & n;
                                if (b != runBit) {
                                    runBit = b;
                                    lastRun = p;
                                }
                            }
                            if (runBit == 0) {
                                ln = lastRun;
                                hn = null;
                            }
                            else {
                                hn = lastRun;
                                ln = null;
                            }
                            for (Node<K,V> p = f; p != lastRun; p = p.next) {
                                int ph = p.hash; K pk = p.key; V pv = p.val;
                                if ((ph & n) == 0)
                                    ln = new Node<K,V>(ph, pk, pv, ln);
                                else
                                    hn = new Node<K,V>(ph, pk, pv, hn);
                            }
                            setTabAt(nextTab, i, ln);
                            setTabAt(nextTab, i + n, hn);
                            setTabAt(tab, i, fwd);
                            advance = true;
                        }
                        else if (f instanceof TreeBin) {
                            TreeBin<K,V> t = (TreeBin<K,V>)f;
                            TreeNode<K,V> lo = null, loTail = null;
                            TreeNode<K,V> hi = null, hiTail = null;
                            int lc = 0, hc = 0;
                            for (Node<K,V> e = t.first; e != null; e = e.next) {
                                int h = e.hash;
                                TreeNode<K,V> p = new TreeNode<K,V>
                                    (h, e.key, e.val, null, null);
                                if ((h & n) == 0) {
                                    if ((p.prev = loTail) == null)
                                        lo = p;
                                    else
                                        loTail.next = p;
                                    loTail = p;
                                    ++lc;
                                }
                                else {
                                    if ((p.prev = hiTail) == null)
                                        hi = p;
                                    else
                                        hiTail.next = p;
                                    hiTail = p;
                                    ++hc;
                                }
                            }
                            ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) :
                                (hc != 0) ? new TreeBin<K,V>(lo) : t;
                            hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) :
                                (lc != 0) ? new TreeBin<K,V>(hi) : t;
                            setTabAt(nextTab, i, ln);
                            setTabAt(nextTab, i + n, hn);
                            setTabAt(tab, i, fwd);
                            advance = true;
                        }
                    }
                }
            }
        }
    }

---158---

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值