二 ConcurrentHashMap源码深度解析(java8)——直呼Dou( 三 )

< 0 ||(a = as[ThreadLocalRandom.getProbe() & m]) == null ||!(uncontended =U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {// 找到对应的格子不为null,则cas 该格子内的value+x// counterCells为空or对应格子为空or update格子失败uncontended=false,// 则进入fullAddCount,这个方法是一定会加成功的,但是加成功就立刻退出整个方法了,不判断扩容了?fullAddCount(x, uncontended);return;}// 从put走到addCount,check是一定>=2的,// 从computeIfAbsent到addCount,可能check =1,意为没有发生哈希冲突的添加元素,则不会检查扩容,// 毕竟扩容是个耗时的操作if (check <= 1)return;// 统计下元素总个数 。s = sumCount();}// 替换节点和清空数组时,check=-1,只做元素个数递减,不会触发扩容检查,也不会缩容 。if (check >= 0) {// 后面触发扩容可以先不看,后面会一起细说 。// 触发扩容判断 代码省略}}
有个疑问,当不得已走到(),这个方法是一定会修改元素个数成功的,但是成功就立刻退出整个方法了,不再向后判断扩容?个人猜想:
1、全力修改元素个数
这个方法有些复杂,但是目的很单纯,就是一定要修改成功 。自旋里可以分为三个大分支:
需要解释两个变量的作用:
private final void fullAddCount(long x, boolean wasUncontended) {int h; // h 类似于 hashif ((h = ThreadLocalRandom.getProbe()) == 0) {// h = 0 则初始化重新获取哈希值,并wasUncontended=true意为没有竞争ThreadLocalRandom.localInit();// force initializationh = ThreadLocalRandom.getProbe();wasUncontended = true;}// false 为没有发生碰撞,竞争// true 的意为升级为严重竞争级别,可能触发扩容boolean collide = false;// True if last slot nonemptyfor (;;) {CounterCell[] as; CounterCell a; int n; long v;if ((as = counterCells) != null && (n = as.length) > 0) {// 1. as不等于null且有CounterCellif ((a = as[(n - 1) & h]) == null) {// (1)映射找到的CounterCell=null,则新建一个if (cellsBusy == 0) {// Try to attach new CellCounterCell r = new CounterCell(x); // Optimistic createif (cellsBusy == 0 &&U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {// cellsBusy 相等于一把乐观锁,到这里说明没有其他线程竞争boolean created = false;try {// Recheck under lockCounterCell[] rs; int m, j;if ((rs = counterCells) != null &&(m = rs.length) > 0 &&rs[j = (m - 1) & h] == null) {// j位置依然是空的,则r赋值给j位置rs[j] = r;// 设置创建成功created = true;}} finally {// 释放锁cellsBusy = 0;}if (created)// 结束循环break;continue;// Slot is now non-empty}}collide = false;}// (2)映射位置的CounterCell不为空,发生哈希冲突else if (!wasUncontended)// CAS already known to fail// (2.1)wasUncontended=false说明有竞争,则不继续向后走去抢了,// 走(5)再哈希,再次循环就认为没有竞争wasUncontended=truewasUncontended = true;// Continue after rehash// (2.2) wasUncontended=true,认为没有竞争,则尝试cas 给该CounterCell里value+xelse if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))// 修改成功就退出了break;// (2.3)修改未成功else if (counterCells != as || n >= NCPU)// (2.3.1)as地址变了(其他线程扩容了) or n即as数组长度已经大于等于cpu核数了// (没有多余的核数给其他线程),就不冲突升级了,走(5)再哈希,再次循环尝试collide = false;// At max size or stale// (2.3.2)counterCells = as && n < NCPUelse if (!collide)// collide=false 则升级冲突级别为true,走(5)再哈希,再次循环尝试collide = true;// (3)已经是严重冲突collide=trueelse if (cellsBusy == 0 &&U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {try {if (counterCells == as) {// Expand table unless stale// counterCells 扩容为 2倍// 这个扩容的触发机制就是映射到的counterCell不为null,且多次尝试cas操作+x失败,// 且当前counterCells地址没有被修改,且数组长度小于NCPU(cpu核数)时触发2倍扩容CounterCell[] rs = new CounterCell[n