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