Полный барьер памяти и 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 это решение пагубной проблемы общего состояния, и поэтому оно специально разработано, чтобы избежать блокировки. Это будет независимо от того, какой пул / диспетчер вы используете.

Другие вопросы по тегам