首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LongAdder Striped64 wasUncontended实现细节

LongAdder Striped64 wasUncontended实现细节
EN

Stack Overflow用户
提问于 2016-12-13 13:05:00
回答 1查看 292关注 0票数 3

这不是一个关于LongAdder如何工作的问题,而是一个我无法理解的有趣的实现细节。

下面是来自Striped64的代码(我已经删除了一些部分,并将相关部分留给了问题):

代码语言:javascript
复制
    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;
        if ((as = cells) != null && (n = as.length) > 0) {
            if ((a = as[(n - 1) & h]) == null) {
                //logic to insert the Cell in the array
            }
            // CAS already known to fail
            else if (!wasUncontended)   {
                wasUncontended = true;      // Continue after rehash
            }
            else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))){
                break;
            }

代码中的许多内容对我来说都很清楚,除了:

代码语言:javascript
复制
        // CAS already known to fail
        else if (!wasUncontended)   {
            wasUncontended = true;      // Continue after rehash
        }

以下CAS将失败的确定性在哪里?这至少对我来说很混乱,因为这个检查只对一个情况是有意义的:当一些线程进入longAccumulate方法的第n次(n > 1)而繁忙的自旋处于第一个周期时。

这段代码是这样说的:如果您(一些线程)以前来过这里,并且在某个特定的单元格槽上有一些争用,那么不要尝试将您的值与已有的值合并,而是重新散列探测。

我真诚地希望我能让某人明白我的意思。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-13 13:42:43

这不是说它会失败,而是它已经失败了。对此方法的调用由LongAdder add方法完成。

代码语言:javascript
复制
public void add(long x) {
    Cell[] as; long b, v; int m; Cell a;
    if ((as = cells) != null || !casBase(b = base, b + x)) {
        boolean uncontended = true;
        if (as == null || (m = as.length - 1) < 0 ||
            (a = as[getProbe() & m]) == null ||
            !(uncontended = a.cas(v = a.value, v + x)))
            longAccumulate(x, null, uncontended);
    }
}
  1. 第一组条件与长细胞的存在有关。如果所需的单元格不存在,那么它将尝试通过原子地添加所需的单元格,然后添加,从而积累没有竞争的单元格(因为没有尝试添加)。
  2. 如果单元格确实存在,请尝试添加(v + x)。如果添加失败,则存在某种形式的争用,在这种情况下,尝试乐观地/原子地进行累积(自旋直到成功)。

所以它为什么

代码语言:javascript
复制
wasUncontended = true;      // Continue after rehash

我最好的猜测是,在竞争激烈的情况下,它将试图给运行的线程时间来追赶,并迫使对现有单元格进行重试。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41121885

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档