<= sc || n >= MAXIMUM_CAPACITY)break;//扩容else if (tab == table) {int rs = resizeStamp(n);//sc<0表示 , 已经有其他线程正在扩容if (sc < 0) {Node[] nt;/**1 (sc >>> RESIZE_STAMP_SHIFT) != rs :扩容线程数 > MAX_RESIZERS-12 sc == rs + 1 和 sc == rs + MAX_RESIZERS :表示什么???3 (nt = nextTable) == null :表示nextTable正在初始化4 transferIndex <= 0 :表示所有hash桶均分配出去*///如果不需要帮其扩容 , 直接返回if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||transferIndex <= 0)break;//CAS设置sizeCtl=sizeCtl+1if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))//帮其扩容transfer(tab, nt);}//第一个执行扩容操作的线程 , 将sizeCtl设置为:(resizeStamp(n) << RESIZE_STAMP_SHIFT) + 2)else if (U.compareAndSwapInt(this, SIZECTL, sc,(rs << RESIZE_STAMP_SHIFT) + 2))transfer(tab, null);}}}此段代码参考网址:
transfer方法private final void transfer(Node[] tab, Node[] nextTab) {int n = tab.length, stride;//计算需要迁移多少个hash桶(MIN_TRANSFER_STRIDE该值作为下限 , 以避免扩容线程过多)if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)stride = MIN_TRANSFER_STRIDE; // subdivide rangeif (nextTab == null) {// initiatingtry {//扩容一倍@SuppressWarnings("unchecked")Node[] nt = (Node[])new Node,?>[n << 1];nextTab = nt;} catch (Throwable ex) {// try to cope with OOMEsizeCtl = Integer.MAX_VALUE;return;}nextTable = nextTab;transferIndex = n;}int nextn = nextTab.length;ForwardingNode fwd = new ForwardingNode(nextTab);boolean advance = true;boolean finishing = false; // to ensure sweep before committing nextTab//1 逆序迁移已经获取到的hash桶集合 , 如果迁移完毕 , 则更新transferIndex , 获取下一批待迁移的hash桶//2 如果transferIndex=0 , 表示所以hash桶均被分配 , 将i置为-1 , 准备退出transfer方法for (int i = 0, bound = 0;;) {Node f; int fh;//更新待迁移的hash桶索引while (advance) {int nextIndex, nextBound;//更新迁移索引i 。if (--i >= bound || finishing)advance = false;else if ((nextIndex = transferIndex) <= 0) {//transferIndex<=0表示已经没有需要迁移的hash桶 , 将i置为-1 , 线程准备退出i = -1;advance = false;}//当迁移完bound这个桶后 , 尝试更新transferIndex ,, 获取下一批待迁移的hash桶else if (U.compareAndSwapInt(this, TRANSFERINDEX, nextIndex,nextBound = (nextIndex > stride ?nextIndex - stride : 0))) {bound = nextBound;i = nextIndex - 1;advance = false;}}//退出transferif (i < 0 || i >= n || i + n >= nextn) {int sc;if (finishing) {//最后一个迁移的线程 , recheck后 , 做收尾工作 , 然后退出nextTable = null;table = nextTab;sizeCtl = (n << 1) - (n >>> 1);return;}if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {/**第一个扩容的线程 , 执行transfer方法之前 , 会设置 sizeCtl = (resizeStamp(n) << RESIZE_STAMP_SHIFT) + 2)后续帮其扩容的线程 , 执行transfer方法之前 , 会设置 sizeCtl = sizeCtl+1每一个退出transfer的方法的线程 , 退出之前 , 会设置 sizeCtl = sizeCtl-1那么最后一个线程退出时:必然有sc == (resizeStamp(n) << RESIZE_STAMP_SHIFT) + 2) , 即 (sc - 2) == resizeStamp(n) << RESIZE_STAMP_SHIFT*///不相等 , 说明不到最后一个线程 , 直接退出transfer方法if ((sc - 2) != resizeStamp(n)
推荐阅读
-
-
-
殴打男孩▲48岁男子电梯内打12岁男孩 被警方采取刑事强制措施
-
【股价】有些上市公司的业绩很好,为什么股价却涨不动?看业绩选股有用吗
-
-
-
嘉欣爱搞笑哪知女友的妈妈在花盆里栽了一颗铁树!,幽默笑话:坐等花开
-
win7旗舰版怎么恢复出厂设置在哪里-dell笔记本Windows7旗舰版怎么恢复出厂设置
-
补血、养血经典方,“妇科第一方”为了你,为了她值得收藏
-
-
这份:新冠肺炎疫情给河北人的生活带来哪些变化?这份大数据告诉你!
-
-
「兰兰水果养生菜肴」鱼汤面营养丰富健康养生,分享简单快捷做鱼汤面的经验,味道鲜美
-
-
-
民生观察厅|因疫情起诉中国只会适得其反,美资深参议员:中国值得尊敬
-
手机拨号没有嘟嘟声,直接提示暂时无法接通?与这几个原因有关
-
您如何看待孩子之间的打闹?父母经常打骂孩子孩子不容易产生哪一种情绪
-
投资|年轻人的胜利!B站业绩太牛了,盘后大涨超7%
-
开盘|绿城管理成功登陆港交所 开盘报价2.65港元/股