volatile
только заставляет ваш код перечитывать значение, но не может контролировать, откуда оно читается. Если значение было недавно прочитано вашим кодом, то оно, вероятно, будет в кеше, и в этом случае volatile заставит его перечитать из кеша, а НЕ из памяти.
В x86 не так много инструкций по связности кэша. Существуют инструкции предварительной выборки, такие как prefetchnta
, но они не влияют на семантику упорядочения памяти. Раньше это реализовывалось путем переноса значения в кэш L1 без загрязнения L2, но все сложнее для современных конструкций Intel с большим общим включительно L3 кешем.
x86 ЦП используют вариант протокола MESI (MESIF для Intel, MOESI для AMD) для обеспечения согласованности своих кэшей (включая частные кэши L1 различных ядер). Ядро, которое хочет записать строку кэша, должно заставить другие ядра сделать недействительной свою копию, прежде чем оно сможет изменить свою собственную копию из общего в измененное состояние.
Вам не нужны никакие инструкции по забору (например, MFENCE) для создания данных в одном потоке и использования их в другом на x86, потому что загрузка / хранение x86 имеет встроенную семантику получения / выпуска . Вам нужен MFENCE (полный барьер), чтобы получить последовательную последовательность. (Предыдущая версия этого ответа предполагала, что требовался clflush
, что неверно).
Вам нужно предотвратить переупорядочение во время компиляции , потому что модель памяти C ++ слабо упорядочена. volatile
старый, плохой способ сделать это; C ++ 11 std :: atomic - гораздо лучший способ написания кода без блокировки.