На самом деле ни кто ни чего не переупорядочивает. Это всего лишь следствие того как разные ядра скидывают свой локальный кэш в ОЗУ.
Вот к примеру есть три переменные A, B, С.
A = C + 1;
B = C + 1;
Чтобы выполнить эти присваивания, Ядро процессора №1 выполняет следующие действия.
1) Загружает переменную C из ОЗУ в Кэш ядра.
...
5) Загружает переменную C из Кэша в Регистр.
6) Увеличивает значение в Регистре на 1.
7) Запишет значение из Регистра в Кэш.
8) Увеличивает значение в Регистре на 1
7) Запишет значение из Регистра в Кэш.
...
20) Вытолкнет из Кэша значение переменной B в ОЗУ.
...
25) Вытолкнет из Кэша значение переменной A в ОЗУ.
Ядра №2,3,4,..N при этом ни чего не знают про значение в Кэше Ядра №1, они видит только ОЗУ. И для них с начало изменится переменная B, а потом через некоторое время переменная А.
Соответствен если вставить барьерную инструкцию, то это заставит Ядро 1 вытолкнуть значение переменно A из Кэша в ОЗУ, до переменной B.
A = C + 1;
memory_barrier();
B = C + 1;
PS Это справедливо для абстрактного процессора в вакууме. Все(кроме NUMA) процессоры с архитектура x86/x64 сделаны так, что все ядра знают про кэши соседних ядер, и соответственно ни каких барьеров памяти в них нет.