2016-12-13 11 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が失敗するという確信はどこにありますか? このチェックは1つのケースにのみ意味があるので、少なくとも私にとっては本当に混乱しています。あるスレッドがlongAccumulateメソッドをn回目(n> 1)に入力し、ビジースピンが最初のサイクル。

あなたが(あるスレッド)以前にここにいて、特定のCellスロットに何らかの競合がある場合は、既存の値にCASの値を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)私はこれがどこから来るのかを知っていますが、それをどちらかの方法で追加することができます。 2)くそー! * CASはすでに失敗していることが分かっている*とは、次のCAS操作が失敗することを意味します。私はあなたの推測が大好きです、彼らはおそらくコードに最適な追加であることを証明するテストを持っていました。あなたのご意見は非常に高く評価されています。 – Eugene

+0

はい、私は今あなたの理論について99%確信しています(コードをもう一度見た後)。それは私には直観的ではありませんが、そのコードを維持している人にとっては、インスタンスの意味があるかもしれません。再度、ありがとうと私はこれを受け入れるでしょう。 – Eugene

+0

これはもっとも賢明な説明です。いつかCASで整数をインクリメントする厳密な競合ループを試してみてください。重大な競合の下では、90%以上のCASが簡単に失敗する可能性があります。 – Voo

関連する問題