Многие знают, что volatile «гарантирует видимость между потоками». Давайте разберёмся, что именно делает это ключевое слово на уровне Java Memory Model (JMM).
В многопроцессорной архитектуре потоки могут обращаться к своим копиям переменных через L1/L2 кэши, а не к основной памяти. Компилятор и процессор активно реорганизуют инструкции (out-of-order, speculative execution), что при отсутствии механизмов синхронизации ведёт к неожиданному поведению в многопоточности.
Если переменная не volatile, один поток может работать со старым значением из кеша и никогда не увидеть обновление другим потоком.
Пример:
class FlagExample {
boolean flag = false;
void thread1() {
while (!flag) {
// бесконечный цикл
}
}
void thread2() {
flag = true;
}
}
JVM и JIT могут оптимизировать while(!flag) так, что значение flag будет читаться один раз и кешироваться локально — и первый поток не выйдет из цикла.
🔹 Гарантирует видимость — каждое чтение/запись идёт из основной памяти, а не из локальных кешей
🔹 Гарантирует порядок операций — volatile запрещает компилятору и процессору менять порядок операций до и после чтения/записи
🔹 Гарантирует правило happens-before — запись в переменную будет видна всем потокам, которые читают её после
Пример:
volatile int counter = 0;
void inc() {
if (counter < 10) {
counter++; // всё ещё не безопасно
}
}
▪️ Не обеспечивает атомарность
counter++ разваливается на чтение → инкремент → запись. Если два потока сделают это одновременно, одно из увеличений потеряется.
Для атомарных операций используйте атомики или синхронизацию.
▪️ Не заменяет synchronized
volatile гарантирует видимость, но не защищает этот блок от одновременного выполнения разными потоками. Для таких случаев используйте synchronized или Lock.
Пример double-checked locking:
class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Без volatile JVM могла бы отдать ссылку на не до конца сконструированный объект.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥3👏2