使用以下代码:
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 + = computationResult.Result生成完整的内存屏障?由于dispatcherQueue不使用Dispatcher,因此线程池将调用AcceptReceiverGroup的Receiver注册中的处理程序。我已经读过线程池为它调用的回调生成一个内存屏障,但是这只能保证回调引用本身的新鲜度吗?
ExclusiveReceiverGroup不与任何其他代码同时运行,因此使用calculateResult.Result递增totalSum不必是原子的。我知道Interlocked.Add会隐式生成一个完整的栅栏,但我只是想看看我是否可以在不使用它的情况下逃脱。
这是一个理论问题。我实际上没有像上面的示例代码那样的代码,并且我没有任何用于此类代码的用例。所以,我想避免“使用Interlocked.Add以防万一”的答案。这更像是“让我们学到新东西”的问题。
答案 0 :(得分:0)
我的理解是,因为ExclusiveReceiverGroup
在任何时候都只有效地执行其委托的单个线程实例,所以不需要(进一步)内存屏障。 ExclusiveReceiverGroup
的重点是解决共享状态的有害问题,因此它是专门设计的,因此可以避免锁定。这与您正在使用的池/调度程序无关。