Полный барьер памяти и ExclusiveReceiverGroup
Со следующим кодом:
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? Обработчик в регистрации Receiver группы ExclusiveReceiverGroup будет вызываться пулом потоков, поскольку dispatcherQueue не использует Dispatcher. Я читал, что пул потоков создает барьер памяти для обратных вызовов, которые он вызывает, но гарантирует ли это только свежесть самой ссылки обратного вызова?
ExclusiveReceiverGroup не запускается одновременно с любым другим кодом, поэтому увеличение totalSum с помощью computationResult.Result не обязательно должно быть атомарным. Я знаю, что Interlocked.Add неявно создает полный забор, но я просто хочу посмотреть, смогу ли я уйти, даже не используя это.
Это теоретическая проблема. На самом деле у меня нет кода, подобного приведенному выше, и у меня нет вариантов использования такого кода. Итак, я хочу избежать ответов "использовать Interlocked.Add на всякий случай". Это скорее вопрос "давайте узнаем что-то новое".
1 ответ
Насколько я понимаю, потому что ExclusiveReceiverGroup
фактически когда-либо только один экземпляр потока своего делегата выполняет только один раз, никакой (дальнейший) барьер памяти не требуется. Весь смысл ExclusiveReceiverGroup
это решение пагубной проблемы общего состояния, и поэтому оно специально разработано, чтобы избежать блокировки. Это будет независимо от того, какой пул / диспетчер вы используете.