使用以下代码:
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不使用分派器,所以ExclusiveReceiverGroup的接收方注册中的处理程序将由线程池调用。我读到线程池为它调用的回调生成一个内存屏障,但这仅仅保证了回调引用本身的新鲜性吗?
ExclusiveReceiverGroup不与任何其他代码并发运行,因此通过computationResult.Result递增totalSum不一定是原子的。我知道Interlocked.Add隐式地生成了一个完整的围栏,但我只是想看看我是否可以不使用它。
这是一个理论问题。实际上,我没有任何类似上面示例代码的代码,我也没有任何此类代码的用例。所以,我想避免“以防万一使用Interlocked.Add”的回答。这更像是一个“让我们学习新东西”的问题。
发布于 2011-03-04 09:21:12
我的理解是,因为ExclusiveReceiverGroup在任何时候只有效地执行其委托的单个线程实例,所以不需要(进一步的)内存屏障。ExclusiveReceiverGroup的全部要点是解决共享状态的有害问题,因此它是专门设计的,这样就可以避免锁定。这与您正在使用的池/分派器无关。
https://stackoverflow.com/questions/5132264
复制相似问题