2016-12-13 48 views
2

这不是关于LongAdder如何工作的问题,而是关于一个有趣的实现细节,我无法弄清楚。LongAdder Striped64 wasUncontended实现细节

下面是从Striped64代码(我剪了一些零部件,并放置问题的相关部分):

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; 
      } 

很多从代码事情是很清楚,我,除了:

 // CAS already known to fail 
     else if (!wasUncontended) { 
      wasUncontended = true;  // Continue after rehash 
     } 

从哪里可以确定下面的CAS会失败?至少这对我来说是很让人困惑的,因为这个检查只对一个案例有意义:当某个线程第n次进入longAccumulate方法(n> 1)并且繁忙的旋转处于第一个循环时。

就像这段代码所说的:如果你(某个线程)之前已经在这里,并且你在特定Cell插槽上有一些争用,请不要试图将CAS值赋给已经存在的值,而是重新刷新探测。

我真的希望我会对某人有所帮助。

回答

3

这并不是说它会失败,它更多的是它失败了。此方法的调用由LongAdderadd方法完成。

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)。如果加载失败则出现了某种形式的争论,在这种情况下,尽量做到累积乐观/原子(自旋,直到成功为止)

那么,为什么它有

wasUncontended = true;  // Continue after rehash 

我最好的猜测是在争议较大的情况下,它会尝试让正在运行的线程赶上并强制重试现有单元。

+3

1)我知道这是从哪里来的,但thx添加它的方式。 2)该死!我认为* CAS已知失败*意味着下一个CAS操作将失败,而不是前一个。我很喜欢你的猜测,他们可能有测试证明这是对代码的最佳补充。非常感谢您的意见。 – Eugene

+0

是的,我现在对你的理论有99%的把握(再次查看代码后)。对我而言,这是违反直觉的,但是对于维护该代码的人来说,这可能会使事例变得有意义。再一次,谢谢你,我会接受这一点。 – Eugene

+0

是的,这是最明智的解释。尝试使用CAS在某个时间递增整数的紧凑竞争循环。在激烈的争论中,你可以很容易地拥有90 +%不成功的CAS。 – Voo