ОК, ключевой момент здесь, как сказал @Maxim, когерентность кэша. В машине, использующей когерентность кэша, это действительно невозможно.
Однако, может работать неправильно на машине без когерентности кэша. Я не знаю конкретной архитектуры, и хотя они почти вымерли из-за естественного отбора, насколько я знаю, некоторые еще остались. (Если вы знаете пример, пожалуйста, прокомментируйте.)
Вот таблица, которая представляет выполнение двух потоков, заполняющих нулевую область в памяти единицами. Для краткости этот пример уменьшен в 32 раза, то есть каждая цифра здесь представляет рассматриваемый 4-байтовый тип int. Размер строки кэша составляет 4 дюйма == 4 цифры. Строки, помеченные как «очищенные», представляют собой точки, в которых кэш-память на кристалле сбрасывается в основную память. В действительности это недетерминировано, как это может случиться в любое время, например, из-за упреждающего переключения задач.
Core 1 cache Memory Core 2 cache
------------------------------------------------------------------------------
0000
0000 (load cache) 0000
1000 (set 1st bit) 0000
1100 (set 2nd bit) 0000 0000 (load cache)
**** (flush) 1100
1100 1000 (set 1st bit)
1000 **** (flush)
1000 1000 (load cache)
1000 1100 (set 2nd bit)
1000 (load cache) 1000 1110 (set 3rd bit)
1010 (set 3rd bit) 1000 1111 (set 4th bit)
1011 (set 4th bit) 1111 **** (flush)
**** (flush) 1011
Итак, в итоге мы получили неверный результат.
Я еще раз подчеркиваю, что этот контрпример действителен только для машин, не связанных с кэшем .