2016-12-13 79 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