И 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-receive и store-release.