Ответ 1
Я считаю, что точка, приведенная в этом примере в спецификации Java, такова, что Ханс Бом и др. пишите в Outlawing Ghosts, и это указывает на недостаток в моделях памяти некоторых современных языков (Java, С++ 11 и даже С++ 14, который адресовал, но не разрешил эту проблему).
Дело в том, что программа, как написано, правильно синхронизирована по правилам языка. (То же самое верно в С++, если вы используете атомарные переменные и memory_order_relaxed
всюду.) Тем не менее, это не запрещено для непредвиденного поведения. Перефразируем Boehm: машина может предположить, что значение, скажем, x
равно 1, затем выполнить результирующую ветвь, а позже (предположительно, когда память наконец ответит), убедитесь, что предположение было истинным. На самом деле найти предположение верно, так как в то же время другой поток действительно сохранил x = 1
, машина продолжает и не откатывается от предполагаемого выполнения.
Чем хуже то, что процессор действительно мог предположить, что существует какое-либо значение. Рассмотрим этот модифицированный пример:
r1 = x | r2 = y
if (r1 != 0) y = r1 | if (r2 != 0) x = r2
В этом случае x
и y
могут по какой-то причине получить любое значение. Машина могла бы предположить, что значение будет чем угодно, а затем спекулятивно продолжить исполнение с этим предположением, а затем найти его предположение, чтобы быть правдой, в пресловутом самоисполняющемся пророчестве.
Возможно, обнадеживает тот факт, что в настоящее время нет реального оборудования в таком виде. Но дело в том, что модели памяти современных языков не запрещают такое поведение. Раздел, который вы цитировали, - это попытка Java сказать: "Посмотрите, мы требуем, чтобы это произошло - до согласованности, но эта другая странная вещь здесь еще не должна произойти". С++ 14 имеет также смутное мнение по этой проблеме в ненормативной заметке 1.10/25.