TGViewer
Библиотека джависта | Java, Spring, Maven, Hibernate Библиотека джависта | Java, Spring, Maven, Hibernate @javaproglib · 22K subscribers
Post #7469 2.77K
🕯 Memory Ordering и happens-before

volatile – это ключевое слово, которое часто используют, но не до конца понимают. Обычно говорят, что оно гарантирует видимость изменений между потоками. На самом деле, смысл этого слова одновременно шире и уже, чем кажется.

🔹 Проблема без volatile


Современные процессоры и компиляторы переупорядочивают инструкции для оптимизации. Каждое ядро имеет store buffer — запись в память не мгновенна, сначала попадает в буфер. Другое ядро может не увидеть запись ещё долгое время.

// Поток 1
data = 42;
ready = true;

// Поток 2
if (ready) {
System.out.println(data); // может напечатать 0
}


Без барьеров компилятор или процессор может переставить data = 42 и ready = true. Или поток 2 увидит ready = true из кеша раньше чем data = 42 из store buffer дойдёт до памяти.

🔹 Что на самом деле гарантирует volatile

Запись в volatile переменную

Сбрасывает store buffer. Все предыдущие записи этого потока становятся видимы другим потокам до того как запись в volatile будет видна.

Чтение volatile переменной

Инвалидирует локальный кеш. Поток видит актуальные значения всех записей, которые произошли до соответствующей volatile-записи в другом потоке.

Это и есть happens-before: если поток A записал в volatile переменную, а поток B прочитал это значение — всё что A делал до записи, видимо B после чтения.

volatile boolean ready;
int data; // не volatile!

// Поток 1
data = 42; // HB-предшествует записи в ready
ready = true; // volatile write

// Поток 2
if (ready) { // volatile read
// data гарантированно == 42
System.out.println(data);
}


data не volatile, но гарантия работает через happens-before цепочку.

🔹 Что volatile не гарантирует

Атомарность составных операций:

volatile long counter;
counter++; // не атомарно: read → increment → write


На 32-битных JVM даже чтение/запись long без volatile не атомарна (два 32-битных слова). volatile long делает операцию атомарной, но counter++ всё равно не атомарна как составная операция.

🔹 Модель памяти Java (JMM) и happens-before

JMM определяет happens-before не только для volatile. Полный список отношений:

— Запись в поле до разблокировки монитора HB разблокировке.
— Разблокировка монитора HB последующей блокировке того же монитора.
— Запись в volatile HB последующему чтению той же переменной.
— Завершение Thread.start() HB любому действию в запущенном потоке.
— Любое действие в потоке HB Thread.join() на этом потоке.

Эти правила транзитивны. Именно на этом строятся корректные публикации объектов: final поля объекта видны всем потокам без дополнительной синхронизации после завершения конструктора, потому что завершение конструктора HB любому доступу к объекту через корректно опубликованную ссылку.

🔹 StampedLock и оптимистичное чтение

StampedLock (Java 8+) предлагает три режима: запись, пессимистичное чтение, оптимистичное чтение. Оптимистичное чтение не берёт блокировку вообще — читает данные и потом валидирует что запись не произошла:

long stamp = lock.tryOptimisticRead();
int x = point.x;
int y = point.y;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
x = point.x;
y = point.y;
} finally {
lock.unlockRead(stamp);
}
}


validate — это volatile-read под капотом, устанавливающий happens-before с последней записью. Паттерн работает корректно именно из-за JMM семантики, а не "просто так".

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#CoreJava
  • 👍 10
  • ❤ 3
  • 🔥 3
More from @javaproglib
  1. Oct 17, 2026☕️ Скользящие окна в Stream без ручного буфера Нужно сравнить соседние измерения или обраб…
  2. Oct 16, 2026🧑‍💻 Какие навыки помогают вам в разработке в 2026 году? Что вы чаще используете в работе…
  3. Oct 16, 2026🧩 Неизменяемый список всё ещё может измениться Collections.unmodifiableList() запрещает м…
  4. Oct 15, 2026💡 Logpoints: логи без правки кода и нового деплоя Чтобы увидеть значение переменной, необ…
  5. Oct 14, 2026Post #7897
  6. Oct 14, 2026Почему разработчик планирует отдавать больше задач Claude Винсент Шмальбах описал план пер…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →