3

これは、LongAdder がどのように機能するかという問題ではなく、私には理解できない興味深い実装の詳細に関する問題です。

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

このコードは次のように言っているようです: あなた (一部のスレッド) が以前にここにいて、特定のセルスロットで競合が発生した場合は、値を既存のものに CAS しようとせず、代わりにプローブを再ハッシュしてください。

正直なところ、誰かにとって意味のあることを願っています。

4

1 に答える 1