Я прочитал статью Синхронизация и Проблемы с многопроцессорностью, и у меня есть вопрос о 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 с более или менее таким же кодом. Одна из рекомендаций Make y interlocked
. Обратите внимание - не одновременно y
и x
.
Обновление
Просто чтобы прояснить вопрос. Дело в том, что я вижу противоречие. В примере из раздела «Проблемы синхронизации и многопроцессорности» используются два InterlockedExchange
. Напротив, в примере 3.1.1 «Базовое переупорядочивание» (который, я думаю, очень похож на первый пример) Херб Саттер дает эту рекомендацию
«Сделайте y взаимосвязанным: если y заблокирован, тогда нет гонки на y, потому что он атомарно обновляется, и нет гонки на x, потому что a -> b -> d».
. В этом черновике Herb не использует две взаимосвязанные переменные (если я прав, он имеет в виду использование InterlockedExchange
только для y
).
fValueHasBeenComputed
. Почему они это сделали, я не знаю. - person jpalecek   schedule 07.10.2011iValue
будет обновляться атомарно (если ваш код не сделает что-то ужасное, чтобы нарушить выравнивание). Так что инструкции в другом потоке не имеют к этому никакого отношения. Более того, даже когда обе переменные обновляются с помощью взаимосвязанных операций, между ними все равно остается интервал, когда инструкции в другом потоке будут видеть значение нервного импульсаiValue
и старое значениеfValueHasBeenComputed
. Таким образом, состояние гонки все еще существует с заблокированным. - person jalf   schedule 07.10.2011CacheComputedValue()
. Однако гонки междуCache...
иFetch...
одинаково невозможны в обоих случаях. Спорить оInterlockedExchange
(особенно если вы не используете его возвращаемое значение) из-за состояния гонки - неуместно. - person jpalecek   schedule 07.10.2011Interlocked...
тоже не решает этого. - person jpalecek   schedule 07.10.2011LONG
на x86 (с использованием определения Win32 дляLONG
) будет (при условии, что ваши данные хорошо выровнены) будет атомарной. И независимо от того, сколько взаимосвязанных операций вы используете, между обновлениемiValue
иfValueHasBeenComputed
будет промежуток, поэтому возникнет потенциальное состояние гонки, если другой код предполагает, что две переменные будут обновлены как одна атомарная операция. - person jalf   schedule 07.10.2011