0

次のコードを使用します。

var dispatcherQueue = new DispatcherQueue();

long totalSum = 0;

Arbiter.Activate(
    dispatcherQueue,
    Arbiter.Interleave(
        new TeardownReceiverGroup(),
        new ExclusiveReceiverGroup(
            Arbiter.Receive<ComputationCompleteResult>(
                true,
                portSet,
                computationResult => totalSum += computationResult.Result
            ),
        new ConcurrentReceiverGroup(
            // Imagine that there is a persistent Receiver registered here
        )
    )
);

totalSum += computeResult.Result の周りに完全なメモリ バリアを生成する必要がありますか? DispatcherQueue は Dispatcher を使用しないため、ExclusiveReceiverGroup のレシーバー登録のハンドラーはスレッド プールによって呼び出されます。スレッド プールが呼び出すコールバックのメモリ バリアを生成することを読みましたが、それはコールバック参照自体の鮮度を保証するだけですか?

ExclusiveReceiverGroup は他のコードと同時に実行されないため、computerResult.Result による totalSum のインクリメントはアトミックである必要はありません。Interlocked.Add が完全なフェンスを暗黙的に生成することは知っていますが、それを使用せずに逃げることができるかどうかを確認したいだけです。

これは理論上の問題です。上記のコード例のようなコードは実際にはありませんし、そのようなコードのユースケースもありません。したがって、「念のため Interlocked.Add を使用する」という回答は避けたいと思います。これは、「何か新しいことを学びましょう」という質問です。

4

1 に答える 1

0

私の理解では、 はExclusiveReceiverGroupデリゲートの単一のスレッド インスタンスを一度に実行するだけなので、(それ以上の) メモリ バリアは必要ありません。の全体的なポイントは、ExclusiveReceiverGroup共有状態の有害な問題に取り組むことであり、ロックを回避できるように特別に設計されています。これは、使用しているプール/ディスパッチャに関係なく発生します。

于 2011-03-04T01:21:12.073 に答える