В моем понимании, если у меня есть:
int xx = x; // read x
int yy = y; // read y
Эти чтения могут быть переупорядочены.
Эти чтения могут быть не только переупорядочены,они могут не произойти вообще.Поток может использовать старое, ранее прочитанное значение для x
и / или y
или значений, которые он ранее записывал в эти переменные, тогда как на самом деле запись, возможно, еще не была выполнена, поэтому «поток чтения» можетиспользуйте значения, о которых другие потоки не могут знать и не находятся в куче памяти в это время (и, вероятно, никогда не будут).
С другой стороны, если у меня есть:
// simplified code, does not compile, but reads happen on the same "this" for example
int xx = VarHandle_X.getOpaque(x);
int yy = VarHandle_Y.getOpaque(y);
На этот раз повторные заказы невозможны?И это то, что означает «программный порядок»?
Проще говоря, главная особенность непрозрачных операций чтения и записи заключается в том, что они действительно произойдут.Это означает, что они не могут быть переупорядочены в отношении другого доступа к памяти, по крайней мере, такой же силы, но это не влияет на обычные операции чтения и записи.
Определен термин программный порядок JLS:
… программный порядок из t - это общий заказ, который отражает порядок, в котором эти действия будут выполняться в соответствии с внутреннимсемантика t .
Это порядок оценки , указанный для выражений и операторов.Порядок, в котором мы воспринимаем эффекты, при условии, что задействован только один поток.
Мы говорим здесь о вставке барьеров для запрета этого переупорядочения?
Нет, в этом нет никакого препятствия, которое может заключаться в фразе «… но без уверенности в эффектах упорядочения памяти по отношению к другим потокам ».
ВозможноМожно сказать, что непрозрачный доступ работает примерно так же, как volatile
до Java 5, обеспечивая доступ для чтения, чтобы увидеть самое последнее значение памяти кучи (что имеет смысл, только если конец записи также использует непрозрачный или даже более сильный режим), нобез влияния на другие операции чтения или записи.
Так что вы можете с этим сделать?
Типичным вариантом использования может быть флаг отмены или прерывания, который не должен устанавливать Происходит до отношений.Часто остановленная фоновая задача не заинтересована в восприятии действий, выполняемых задачей остановки перед передачей сигналов, а просто прекращает свою собственную деятельность.Поэтому написание и чтение флага в непрозрачном режиме было бы достаточным для обеспечения того, чтобы сигнал в конечном итоге был замечен (в отличие от обычного режима доступа), но без какого-либо дополнительного негативного влияния на производительность.
Аналогично, фоновая задача могла бызаписывать обновления хода выполнения, например, процентное число, которое поток отчетов (UI) должен своевременно замечать, в то время как перед публикацией окончательного результата отношения произойдет до не требуются.
Это также полезно, если вы просто хотите атомарный доступ для long
и double
, без каких-либо других последствий.
Поскольку действительно неизменяемые объекты, использующие поля final
, защищены от гонок данных, вы можете использовать непрозрачные режимы длясвоевременная публикация неизменяемых объектов без более широкого эффекта публикации в режиме выпуска / приобретения.
Особый случай - периодическая проверка состояния на предмет ожидаемого обновления значения и его доступности, запрос значения с более сильным режимом (или выполнениесоответствующий забор инструкциина явно).В принципе, отношение случай-до может быть установлено только между записью и ее последующим чтением в любом случае, но так как оптимизаторы обычно не имеют горизонта для идентификации такого случая использования между потоками, код, критичный для производительностиможно использовать непрозрачный доступ для оптимизации такого сценария.