Я прочитал статью Проблемы синхронизации и многопроцессорности , и у меня есть вопрос о 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 Native Code . Есть пример 3.1.1 с более или менее таким же кодом. Одна из рекомендаций Сделайте y заблокированным
. Обратите внимание - не одновременно y
и x
.
Обновление
Просто чтобы прояснить вопрос. Дело в том, что я вижу противоречие. В примере из «Проблемы синхронизации и многопроцессорности» используются два InterlockedExchange
. Напротив, в примере 3.1.1 «Базовое переупорядочение» (который, я думаю, очень похож на первый пример) Херб Саттер дает эту рекомендацию
«Сделайте y блокированным: если y блокируется, то гонки на y , потому что он обновляется атомарно, и нет гонки по x, потому что a -> b -> d. "
.В этом проекте Herb не использует две взаимосвязанные переменные (если я прав, он имеет в виду использование InterlockedExchange
только для y
).