Я прочитал статью Проблемы с синхронизацией и многопроцессорностью , и у меня есть вопрос о InterlockedCompareExchange и InterlockedExchange. Вопрос на самом деле о последнем примере в статье. У них есть две переменные iValue
и fValueHasBeenComputed
, а в CacheComputedValue()
они изменяют каждую из них, используя InterlockedExchange
:
InterlockedExchange ((LONG*)&iValue, (LONG)ComputeValue()); // don't understand
InterlockedExchange ((LONG*)&fValueHasBeenComputed, TRUE); // understand
Я понимаю, что могу использовать InterlockedExchange
для модификации iValue
, но достаточно ли это просто, чтобы сделать
iValue = ComputeValue();
Так действительно ли необходимо использовать InterlockedExchange
для установки iValue? Или другие потоки будут правильно видеть iValue, даже если iValue = ComputeValue();
. Я имею в виду, что другие потоки будут правильно видеть iValue, потому что после него стоит InterlockedExchange
.
Существует также статья Принципиальная модель последовательной памяти для платформ собственного кода Microsoft . Есть пример 3.1.1 с более или менее одинаковым кодом. Одна из рекомендаций Make y interlocked
. Обратите внимание - не оба y
и x
.
Обновление
Просто чтобы уточнить вопрос. Проблема в том, что я вижу противоречие. Пример из «Проблемы синхронизации и многопроцессорности» использует два InterlockedExchange
. Напротив, в примере 3.1.1 «Базовый перезапись» (который, я думаю, очень похож на первый пример) Херб Саттер дает эту рекомендацию
"Сделать y заблокированным: если y заблокирован, то на y нет гонки
потому что это атомно обновляемый, и нет никакой гонки на х, потому что
-> b -> d. "
. В этом проекте Херб не использует две взаимосвязанные переменные (если я прав, он подразумевает использование InterlockedExchange
только для y
).