Неустойчивые переменные и происходит перед заказом
У меня есть два потока:
Тема: 1
a = 1;
x = b;
Тема: 2
b = 1
y = a
Здесь a и b объявлены изменчивыми. Я не понял, как создается "случается-до" ребро между a = 1; и y = a; и между x = b; и b = 1;
Я понимаю, что с помощью переменной volatile можно предотвратить чтение устаревших значений из кэша потоков. Но как можно избежать изменчивой переменной - перед заказом.
В частности, я не понял этого:
запись в нестабильное поле происходит перед каждым последующим чтением то же поле.
Hoe это работает?
Ответы
Ответ 1
запись в изменчивое поле происходит до каждого последующего чтения того же поля.
Важное слово здесь - "последующее".
Здесь соответствующий бит спецификации языка Java 17.4.4 Порядок синхронизации:
Каждое исполнение имеет порядок синхронизации. Порядок синхронизации - это полный порядок по всем действиям синхронизации выполнения. Для каждого потока t порядок синхронизации действий синхронизации (§17.4.2) в t соответствует порядку программы (§ 17.4.3) t. Действия синхронизации индуцируют синхронизированную связь с действиями, определенную следующим образом:
- [...]
- Запись в изменчивую переменную (§8.3.1.4) v синхронизируется со всеми последующими чтениями v любым потоком (где последующее определяется в соответствии с порядком синхронизации).
Обратите внимание на последнюю часть. Поэтому, говоря о том, что если вы рассматриваете любой общий порядок действий программы, любое чтение изменчивой переменной, которая приходит позже в этом полном порядке, чем запись, не может "пропустить" запись.
Ответ 2
запись в изменчивое поле происходит перед каждым последующим чтением того же поля.
Этот текст является чем-то запутанным. Это ограничивает связь между случаями и событиями до того, как это произойдет - до чтения! Он только говорит, что читает, что происходит после, на самом деле происходит после.
Другими словами, то, что он пытается сказать, заключается в том, что чтение не происходит во время записи, а также, если есть другие события-до отношений, которые заставляют чтение читать после записи, что чтение будет иметь значение записи.
См. раздел JLS 17.4.4 Порядок синхронизации, который определяет слово "последующее" в этом контексте.
Ответ 3
Для анализа сначала укажите все возможные заказы синхронизации. они должны соответствовать порядку программирования. В вашем примере есть 6 возможных заказов.
1 2 3 4 5 6
w(a) w(a) w(b) w(a) w(b) w(b)
r(b) w(b) w(a) w(b) w(a) r(a)
w(b) r(b) r(b) r(a) r(a) w(a)
r(a) r(a) r(a) r(b) r(b) r(b)
Каждый порядок устанавливает некоторые действия перед отношениями. В (1) имеем w (a) - до r (a). В (6) имеем w (b) - до r (b). В (2) - (5) имеем оба.
Для каждого возможного порядка, с учетом установленных ранее отношений, вам необходимо проанализировать выполнение, чтобы убедиться, что оно делает то, что вы хотите.
Если это звучит слишком сложно, это так. В реальной жизни мы обычно ограничиваемся более простыми ситуациями, когда только один объект заблокирован/выпущен, или только одна изменчивая переменная читается и записывается. Тогда это не слишком сложно.