На эту тему есть неплохая статья на https://habr.com/ru/post/133981/ либо можно скачать полную спецификацию работы JMM(java memory model) https://download.oracle.com/otndocs/jcp/memory_model-1.0-pfd-spec-oth-JSpec/
Если вкратце, reodering - это то в каком порядке выполняются операции и доступ потоков, а набор правил описаны в соотношении happens before.
public class Data { int maxAllowedValue; public Data() { this.maxAllowedValue = 9000; } }
public class Keeper { private Data data = null; public Data getData() { if(data == null) { synchronized(this) { if(data == null) { data = new Data(); } } } return data; } }
Поток, который первый обнаружит, что data == null
, выполнит следующие действия:
- Выделит память под новый объект
- Вызовет конструктор класса
Data
- Запишет значение 9000 в поле
maxAllowedValue
классаData
- Запишет только что созданный объект в поле
data
классаKeeper
Другой поток может увидеть произошедшее в пункте 4 до того, как он увидит произошедшее в пунктах 3, т.е не в том порядке в которым логично ожидать, поэтому был создан набор правил, по которым оптимизатору/компилятору запрещено выполнять reordering. Набор правил описан через соотношение happens before:
1.Освобождение (releasing) монитора happens-before заполучение (acquiring) того же самого монитора
2.Запись в volatile переменную happens-before чтение из той же самой переменной
3. Запись значения в final
-поле при конструировании объекта happens-before запись этого объекта в какую-либо переменную, происходящая вне этого конструктора.
No comments:
Post a Comment