Записывает ли Java volatile чтение флеша и выполняет ли обновление volatile write update
Я понимаю, что read-приобретает (не переупорядочивает с последующими операциями чтения/записи после него) и write-release (не переупорядочивает с предшествующими им операций чтения/записи).
Мой q: -
- В случае чтения-получения, предшествуют ли записи, сделанные после этого?
- В случае записи-записи обновить предыдущие чтения?
Кроме того, читается-приобретает то же самое, что и volatile read, и записывает release так же, как volatile write в Java?
Почему это важно, так это, чтобы взять случай с записью-релизом.
y = x; // a read.. let say x is 1 at this point
System.out.println(y);// 1 printed
//or you can also consider System.out.println(x);
write_release_barrier();
//somewhere here, some thread sets x = 2
ready = true;// this is volatile
System.out.println(y);// or maybe, println(x).. what will be printed?
В этот момент, x 2 или 1?
Здесь рассмотрим готовность к летучести.
Я понимаю, что все хранилища до волатильности будут сначала видимыми.. и тогда только изменчивые будут видны. Спасибо.
Ссылка: - http://preshing.com/20120913/acquire-and-release-semantics/
Ответы
Ответ 1
Нет: не все записи сбрасываются и не обновляются все.
Java работает над принципом "когда-то" для многопоточности. В основном, если A происходит до B, а B - до C, то A происходит до C. Таким образом, ваш вопрос состоит в том, формально ли x=2
- перед некоторым действием, которое читает x.
Случается, что перед ребрами в основном устанавливаются синхронизирующие отношения с отношениями, которые определены в JLS 17.4.4. Существует несколько разных способов сделать это, но для летучих, это в основном сводится к тому, что запись волатильна - до того, как будет прочитано то же самое изменчивое:
- Запись в изменчивую переменную v (§8.3.1.4) синхронизируется со всеми последующими чтениями v любым потоком (где "последующий" определяется в соответствии с порядком синхронизации).
Учитывая, что если ваш поток пишет ready = true
, то сама запись не означает, что что-либо происходит - перед ним (насколько это касается записи). Это наоборот; которые пишутся в ready
, - перед событиями в других потоках, если они читают ready
.
Итак, если другой поток (который устанавливает x = 2
) был написан до готовности после того, как он установил x = 2
, и этот поток (который вы разместили выше), затем прочитайте ready
, тогда он увидит x = 2
. Это происходит потому, что запись происходит - перед чтением, и поток чтения, следовательно, видит все, что написал поток писем (вплоть до и включая запись). В противном случае у вас есть гонка данных, и в основном все ставки отключены.
Несколько дополнительных примечаний:
- Если у вас нет прецедента до переднего края, вы все равно можете увидеть обновление; это просто, что вам не гарантировано. Итак, не предполагайте, что если вы не прочитали запись в
ready
, вы все равно увидите x = 1. Вы можете увидеть x = 1 или x = 2 или, возможно, другую запись (вплоть до значения по умолчанию x = 0)
- В вашем примере
y
всегда будет 1, потому что вы не перечитываете x
после комментария "где-то здесь". Для целей этого ответа я предположил, что есть вторая строка y=x
непосредственно перед или после ready = true
. Если нет, то значение y останется неизменным от того, что было в первом println
(если ни один другой поток не изменил его напрямую, что гарантировано, если это локальная переменная), потому что действия внутри потока всегда отображаются так, как если бы они не переупорядочиваются.
Ответ 2
Модель памяти Java не указывается в терминах "чтение-получение" и "запись-релиз". Эти термины/понятия исходят из других контекстов, и поскольку статья, на которую вы ссылаетесь, делает это совершенно ясно, они часто используются (разными экспертами), чтобы обозначать разные вещи.
Если вы хотите понять, как работают летучие мыши на Java, вам нужно понять модель памяти Java и терминологию Java... которая (к счастью) обоснована и точно определена 1. Попытка сопоставить модель памяти Java с семантикой "чтение-получение" и "запись-релиз" - это плохая идея, потому что:
-
Терминология и семантика "чтение-получение" и "запись-релиз" не определены, и
-
гипотетическое JMM → "чтение-получение" / "запись-релиз" семантического сопоставления - это только одна возможная реализация JMM. Другие сопоставления могут существовать с различной и одинаково допустимой семантикой.
1 -... по модулю, что эксперты отметили недостатки в некоторых версиях JMM. Но дело в том, что была предпринята серьезная попытка предоставить теоретически обоснованную спецификацию... как часть спецификации языка Java.
Ответ 3
Нет, чтение изменчивой переменной не будет сбрасывать предыдущие записи. Видимые действия гарантируют, что предыдущие действия видны, но чтение изменчивой переменной не видимо для других потоков.
Нет, запись в переменную volatile не очищает кеш ранее прочитанных значений. Гарантируется только сброс предыдущей записи.
В вашем примере ясно, что y
по-прежнему будет 1 в последней строке. Только одно назначение было сделано для y
, и это было 1, согласно предыдущему выводу. Возможно, это была опечатка, и вы хотели написать println(x)
, но даже тогда значение 2 не гарантируется быть видимым.
Ответ 4
Для вашего 1-го вопроса ответ заключается в том, что FIFO-заказ
Для вашего второго вопроса: pls check Летучие Vs Статические в java