LongAdder中的longAccumulate方法中关于rehash的问题?

新手上路,请多包涵

longAccumulate方法中有一个地方我觉得不需要rehash,搞不清楚为什么这里需要rehash。直接贴代码吧,重点问题我写在了这段代码的下面。

    final void longAccumulate(long x, LongBinaryOperator fn,
                              boolean wasUncontended) {
        int h;
        if ((h = getProbe()) == 0) {
            ThreadLocalRandom.current(); // force initialization
            h = getProbe();
            wasUncontended = true;
        }
        // 是否需要扩容
        boolean collide = false;                // True if last slot nonempty
        for (;;) {
            Cell[] as; Cell a; int n; long v;
            // 判断cells非空并且其长度不为0,说明不存在竞争
            if ((as = cells) != null && (n = as.length) > 0) {
                // 获取下标位置的Cell如果为空
                if ((a = as[(n - 1) & h]) == null) {
                    if (cellsBusy == 0) {}
                    // 表示暂时还不需要扩容
                    collide = false;
                }
                // 说明cas失败,在add方法中,能走到以下的else说明当前下标位置已经有东西了
                else if (!wasUncontended)       // CAS already known to fail
                    wasUncontended = true;      // Continue after rehash 发现有竞争后rehash重试
                // 看一下能不能直接CAS设置成功,不能的话继续向下走
                else if (a.cas(v = a.value, ((fn == null) ? v + x :
                                             fn.applyAsLong(v, x)))) // 如果再次设置失败,继续向下执行elseif
                    break;
                else if (n >= NCPU || cells != as)
                    collide = false;            // At max size or stale
                else if (!collide) //
                    collide = true; // 只能理解为再试一次了,再试一次还是不行那就只能扩容了
                else if (cellsBusy == 0 && casCellsBusy()) {
                }
                // 这里会rehash
                h = advanceProbe(h);
            }
            else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
            }
            else if (casBase(v = base, ((fn == null) ? v + x :
                                        fn.applyAsLong(v, x))))
                break;                          // Fall back on using base
        }
    }

我们看下这段代码:

            if ((a = as[(n - 1) & h]) == null) {
                if (cellsBusy == 0) {}
                // 表示暂时还不需要扩容
                collide = false;
            }

如果cellsBusy不为0,则表示CAS锁正在被占用,然后会执行collide=false这句代码,再然后执行完这个条件分支后会进行rehash,就是执行 h = advanceProbe(h);这句代码,我想问,为什么需要rehash啊?as[(n - 1) & h]这个位置不已经是空的吗?只是占时没获取到CAS锁而已,所以才没有向里面填值,但是我觉得只要重循环一下,如果cellsBusy未被占用,直接继续在这个位置赋值就行,为什么还要rehash换位置呢?

阅读 1.2k
2 个回答
新手上路,请多包涵

那万一下一次来它还是获取不到锁呢?还不如rehash让它重新找个坑儿

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏