これは、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しないでください。プローブ。
私は正直なところ、私は誰かのために意味を作ってくれることを願っています。
1)私はこれがどこから来るのかを知っていますが、それをどちらかの方法で追加することができます。 2)くそー! * CASはすでに失敗していることが分かっている*とは、次のCAS操作が失敗することを意味します。私はあなたの推測が大好きです、彼らはおそらくコードに最適な追加であることを証明するテストを持っていました。あなたのご意見は非常に高く評価されています。 – Eugene
はい、私は今あなたの理論について99%確信しています(コードをもう一度見た後)。それは私には直観的ではありませんが、そのコードを維持している人にとっては、インスタンスの意味があるかもしれません。再度、ありがとうと私はこれを受け入れるでしょう。 – Eugene
これはもっとも賢明な説明です。いつかCASで整数をインクリメントする厳密な競合ループを試してみてください。重大な競合の下では、90%以上のCASが簡単に失敗する可能性があります。 – Voo