Ответ 1
Оба MemoryBarrier
(MSVC) и _mm_mfence
(поддерживаемые несколькими компиляторами) обеспечивают ограждение аппаратной памяти, что препятствует переходу процессора на чтение и запись через забор.
Основное различие заключается в том, что MemoryBarrier имеет специфичные для платформы реализации для x86, x64 и IA64, где в качестве _mm_mfence специально используется команда mfence
SSE2, поэтому она не всегда доступна.
В x86 и x64 MemoryBarrier реализованы с xchg
и lock or
соответственно, и я видел некоторые утверждения о том, что это быстрее, чем mfence. Однако мои собственные тесты показывают противоположное, поэтому, по-видимому, он очень сильно зависит от модели процессора.
Другое отличие заключается в том, что mfence также может использоваться для упорядочения невременных хранилищ/нагрузок (movntq
и т.д.).
GCC также имеет __sync_synchronize
, который генерирует аппаратный забор.
asm volatile ("" : : : "memory")
в GCC и _ReadWriteBarrier
в MSVC обеспечивают только ограждение памяти уровня компилятора, не позволяя компилятору переупорядочивать доступ к памяти. Это означает, что процессор по-прежнему свободен для переупорядочения.
Запонки компилятора обычно используются в сочетании с операциями, которые имеют своего рода неявный аппаратный забор. Например. на x86/x64 все магазины имеют заборный забор, а нагрузка имеет забор, поэтому вам нужно только ограждение компилятора при реализации load-purchase и store-release.