Проблема здесь - чтение-изменение-запись.
Допустим, у вас есть два отдельных физических ядра (они могут быть в одном физическом пакете). Они оба читают. Первое ядро модифицирует, то есть увеличивает значение, которое в данный момент хранится в регистре. В этот момент модификация начинает распространяться на кеши, но второе ядро тем временем также изменило значение и также начало распространять кеш в кеш.
Вы потеряете одно из обновлений.
Протоколы когерентности кэша не обрабатывают случай множественных одновременных записей. Нет ничего, что заставляло бы одно ядро ждать своей записи, потому что другое ядро также в настоящее время пишет; потому что эта информация просто не доступна публично между ядрами. Они не могут этого сделать.
Они обрабатывают несколько последовательных записей, например, после того, как изменения были замечены на ядре, выводы внешней шины (например, стали общедоступными, а не внутренними по отношению к ядру).
Другая проблема - это переупорядочивание команд. Эти потоки - если они работают на разных ядрах, их переупорядочение команд не будет обращать внимания на то, что делают другие потоки; только к тому, что конкретно делает этот поток.
Представьте, что один поток собирается записать значение, а затем установить флаг. Другой поток увидит поднятый флаг и затем прочитает значение. Эти потоки, если они находятся на отдельных ядрах, будут переупорядочивать свои потоки команд только в отношении самих себя - ядра не будут учитывать другие потоки, потому что они не могут - они не знают о них.
Таким образом, в первом потоке настройку флага можно переупорядочить, чтобы она произошла за до записи значения - в конце концов, для только для этого потока это переупорядочение хорошо. Эти две переменные полностью отключены. Там нет упорядочения зависимости. Зависимость существует в другом потоке на другом ядре , поэтому наше ядро не может знать об этом.
Другой поток, конечно, увидит поднятый флаг и прочитает его, хотя запись на самом деле еще не произошла.