曹工说JDK源码(3)--ConcurrentHashMap,Hash算法优化、位运算揭秘 (3)

所以,RESIZE_STAMP_SHIFT 为16.

0000 0000 0000 0000 1000 0000 0001 1101 -- 相当于把29的第一位,变成了1,其他都没变。 1000 0000 0001 1101 0000 0000 0000 0000 --- 左移16位,即 rs << RESIZE_STAMP_SHIFT 1000 0000 0001 1101 0000 0000 0000 0010 -- (rs << RESIZE_STAMP_SHIFT) + 2)

最终,这个数,第一位是 1,说明了,这个数,肯定是负数。

大家如果看过其他人写的资料,也就知道,当sizeCtl为负数时,表示正在扩容。

所以,这里

if (U.compareAndSwapInt(this, SIZECTL, sc, (rs << RESIZE_STAMP_SHIFT) + 2))

这句话就是,如果当前线程成功地,利用cas,将sizeCtl从正数,变成负数,就可以进行扩容。

扩容时,其他线程怎么执行 // 1 if (bContinue) { int rs = resizeStamp(n); // 2 if (sc < 0) { // 2.1 if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 || sc == rs + MAX_RESIZERS || (nt = nextTable) == null || transferIndex <= 0) break; // 2.2 if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) transfer(tab, nt); } // 3 else if (U.compareAndSwapInt(this, SIZECTL, sc, (rs << RESIZE_STAMP_SHIFT) + 2)) transfer(tab, null); newBaseCount = sumCount(); } else { break; }

此时,因为上面的线程触发了扩容,sc已经变成了负数了,此时,新的线程进来,会判断2处。

2处是满足的,会进入2.1处判断,这里的部分条件看不懂,大概是:扩容已经结束,就不再执行,直接break

否则,进入2.2处,辅助扩容,同时,把sc变成sc + 1,增加扩容线程数。

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

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