Java Memory Model — это формальная спецификация, которая определяет:
Видимость изменений (Visibility):
Порядок выполнения (Ordering):
Атомарность операций:
Отношение порядка между операциями, гарантирующее видимость изменений:
Если операция A happens-before операции B, то результат A виден для B
Примеры happens-before:
Поток 1: Working Memory ←→ Main Memory
Поток 2: Working Memory ←→ Main Memory
Гарантируют:
volatile boolean flag = false;
// Поток 1:
flag = true; // Запись сразу видна другим потокам
// Поток 2:
while(!flag); // Увидит изменение немедленно
Правильные способы опубликовать объект для других потоков:
// 1. Через volatile
volatile MyObject obj;
// 2. Через final поля
class Holder {
final MyObject obj;
Holder(MyObject o) { this.obj = o; }
}
// 3. Через synchronized
synchronized void setObject(MyObject o) {
this.obj = o;
}
В Android часто используют:
@GuardedBy("lock")
private Object sharedData;
@Volatile
private boolean isReady;
// Без синхронизации может работать некорректно
boolean running = true;
void stop() { running = false; } // Может никогда не стать видимым
// JVM может поменять порядок инициализации
objRef = new Object(); // Часть 1: выделение памяти
// Часть 2: инициализация (может быть переупорядочена)
Для synchronized:
Для final полей:
Для volatile:
Java Memory Model — это фундаментальная спецификация, определяющая правила работы с памятью в многопоточной среде. Понимание JMM критически важно для написания корректных concurrent-приложений в Android, особенно при работе с SharedPreferences, LiveData и другими компонентами, где важна видимость изменений между потоками.