sizeCtl的含义
- 为0: 代表数组没有初始化
- 为正数:
- 数组已经初始化,记录的是数组的扩容阈值
- 如果没有初始化,记录的是数组初始容量
- 为-1: 代表数组正在初始化中
-
transfer 扩容
```java private final void transfer(Node
[] tab, Node [] nextTab) { int n = tab.length, stride;if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)// stride 每个线程要领多少个任务,也计数要迁移多少个位置stride = MIN_TRANSFER_STRIDE; // stride肯定大于16if (nextTab == null) { // initiatingtry {@SuppressWarnings("unchecked")Node<K,V>[] nt = (Node<K,V>[])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<K,V> fwd = new ForwardingNode<K,V>(nextTab);boolean advance = true;boolean finishing = false; // 所有线程是否完成扩容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))) { //将transferIndex设置为 老数组的长度-16 或者 0bound = nextBound; //老数组的长度-16 或者 0i = nextIndex - 1; //老数组的长度-1advance = 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}}else if ((f = tabAt(tab, i)) == null) //如果当前位置为空 那么赋值fwdadvance = casTabAt(tab, i, null, fwd);else if ((fh = f.hash) == MOVED) //如果已经迁移完成了 那么什么都不干advance = true; // already processedelse {synchronized (f) { //防止迁移的时候 别的线程加数据if (tabAt(tab, i) == f) {Node<K,V> ln, hn;if (fh >= 0) {int runBit = fh & n;Node<K,V> lastRun = f;//区别数据 假设现在迁移的位置 是个链表 size是6 那么可能还是3个保留在原来的位置 还有3个放置到原来的位置+老数组的长度位置上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);elsehn = 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;elseloTail.next = p;loTail = p;++lc;}else {if ((p.prev = hiTail) == null)hi = p;elsehiTail.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;}}}}}
}
(resizeStamp(n) << RESIZE_STAMP_SHIFT) + 2)(sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT
```
