f; int fh;while (advance) {int nextIndex, nextBound;// (1)两种情况不需要继续向前一个位置迁移复制元素(逆序):// ①i每次自减1,i>=bound说明本批次迁移未完成,不需要继续向前推进 。// ②finishing标志为true,说明所有线程分配的迁移任务都已经完成了,则不需要向前推进 。// 若 --i < bound,说明当前批次的迁移任务完成,可继续分配新范围的任务// 也就是一个线程可以多次分到任务,能者多劳 。if (--i >= bound || finishing)// 向前一个位置迁移复制元素advance = false;//(2) 每次执行,都会把 transferIndex 最新的值同步给 nextIndexelse if ((nextIndex = transferIndex) <= 0) {//若 transferIndex小于等于0,则说明原数组中所有位置的迁移任务都分配完毕(不代表所有位置都迁移完毕)//于是,需要跳出while循环,并把 i设为 -1,// 以跳到(4)判断正在处理的线程是否完成自己负责范围内迁移工作 。i = -1;advance = false;}else if (U.compareAndSwapInt(this, TRANSFERINDEX, nextIndex,nextBound = (nextIndex > stride ?nextIndex - stride : 0))) {//(3)cas 设置TRANSFERINDEX,分配任务范围[nextBound,nextIndex),任务的长度是stride// 举例,假设 n=64,即初始的transferIndex=64,stride=16// nextIndex=transferIndex=64,nextBound=nextIndex-stride=48// bound=48// i=63// 从后往前复制bound = nextBound;i = nextIndex - 1;advance = false;// 本次任务分配完成,结束循环}}// (4)i已经越界了,整个数组的迁移任务已经全部分配完毕if (i < 0 || i >= n || i + n >= nextn) {int sc;if (finishing) {// 扩容完毕// nextTable置为空nextTable = null;// 新数组赋值给旧数组table = nextTab;// sizeCtl 设置为新的数组长度的 3/4.即 3/4 *2nsizeCtl = (n << 1) - (n >>> 1);return;}// 到这,说明所有的迁移任务都分配完了// 当前线程也已经完成了自己的迁移任务(无论参与了几次迁移),// 则sc-1,表明参与扩容的线程数减1if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {// 迁移开始时,会设置 sc=(rs << RESIZE_STAMP_SHIFT) + 2// 每当有一个线程参与迁移,sc 就会加 1 。// 因此,这里就是去校验当前 sc 是否和初始值相等 。if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)// 不相等,当前线程扩容任务结束 。return;// 相等,说明还有一个线程还在扩容迁移(不一定是触发扩容的第一个线程)// 则当前线程会从后向前检查一遍,哪些位置的节点没有复制完,就帮忙一起复制 。// 一圈扫描下来,肯定是全部迁移完毕了,则finishing可提前设置为true 。finishing = advance = true;i = n; // recheck before commit}}else if ((f = tabAt(tab, i)) == null)// (5)若i的位置元素为空,就把占位节点设置为fwd标志 。// 设置成功,advance置为true,向前推进复制 advance = casTabAt(tab, i, null, fwd);else if ((fh = f.hash) == MOVED)// (6)若当前位置的头结点是 ForwardingNode ,则说明这个位置的所有节点已经迁移完成,// 可以继续向前迁移复制其他位置的节点advance = true; // already processedelse {// (7)对tab[i]进行迁移,可能是链表 or 红黑树synchronized (f) {if (tabAt(tab, i) == f) {Node ln, hn;if (fh >= 0) {// 链表int runBit = fh & n;Node lastRun = f;// lastRun并不是一条链表的最后一个,一条链表的节点可以分为两类,// 在循环中寻找lastRun的满足条件是链表中最后一个与前一个节点runBit不相等的节点作为lastRun,// 而此时lastRun后面可能还有节点,但runBit都是和lastRun相等的节点 。// 这里找lastRun和java7是一样的for (Node p = f.next; p != null; p = p.next) {// 计算p的位置int b = p.hash & n;if (b != runBit) {// 和runBit不是同一位置runBit = b;lastRun = p;}}// hash & n=0为低位节点,hash & n!=0为高位节点 。// 判断找到的lastRun是低位节点还是高位节点if (runBit == 0) {ln = lastRun;hn = null;}else {hn = lastRun;ln = null;}// lastRun之前的结点因为fh&n不确定,所以全部需要再hash分配 。for (Node