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 生成一个完整的内存屏障?ExclusiveReceiverGroup的Receiver注册中的handler会被线程池调用,因为dispatcherQueue不使用Dispatcher。我读过线程池为它调用的回调生成了一个内存屏障,但这是否只是保证回调引用本身的新鲜度?

ExclusiveReceiverGroup 不会与任何其他代码同时运行,因此通过computationResult.Result 递增totalSum 不必是原子的。我知道 Interlocked.Add 隐式生成一个完整的栅栏,但我只是想看看我是否可以不使用它而逃脱。

这是一个理论问题。我实际上没有像上面的示例代码那样的任何代码,也没有此类代码的任何用例。所以,我想避免“使用 Interlocked.Add 以防万一”的答案。这更像是一个“让我们学习新东西”的问题。

4

1 回答 1

0

我的理解是,因为在ExclusiveReceiverGroup任何时候只有效地执行其委托的单个线程实例,所以不需要(进一步的)内存屏障。的全部意义ExclusiveReceiverGroup在于解决共享状态的有害问题,因此它是专门设计的,因此可以避免锁定。这与您使用的池/调度程序无关。

于 2011-03-04T01:21:12.073 回答