← Назад к вопросам
Будет ли атомарная операция с volatile переменной?
2.4 Senior🔥 191 комментариев
#JVM и управление памятью#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Будет ли атомарная операция с volatile переменной?
Краткий ответ
Нет, volatile не гарантирует атомарность операций. volatile обеспечивает только видимость изменений между потоками, но не обеспечивает атомарность составных операций.
Что такое volatile?
volatile — это модификатор в Java, который:
public class VolatileExample {
private volatile int counter = 0; // видно всем потокам
}
Гарантии volatile:
- ✅ Видимость (visibility) — изменения видны всем потокам
- ✅ Запрет на переупорядочивание (memory barriers)
- ❌ Не защищает от race conditions
- ❌ Не атомарна
Почему volatile не атомарен?
Атомарность — это неделимость операции, выполняемой как одна единица. Рассмотрим пример:
public class NonAtomicVolatile {
private volatile long value = 0;
// Составная операция (не атомарна!)
public void increment() {
value++; // 3 операции: read -> add -> write
}
public long getValue() {
return value;
}
}
Что происходит при value++ с двумя потоками:
Поток 1: read (0) -> add -> write (1)
Поток 2: read (0) -> add -> write (1)
Результат: 1 вместо 2 (race condition)
Dаже с volatile, оба потока читают 0, увеличивают до 1 и записывают 1. Одно значение потеряно.
Как обеспечить атомарность?
Вариант 1: synchronized
public class AtomicWithSync {
private volatile long value = 0;
public synchronized void increment() {
value++; // Теперь атомарна
}
public synchronized long getValue() {
return value;
}
}
Вариант 2: AtomicLong (рекомендуется)
public class AtomicExample {
private AtomicLong counter = new AtomicLong(0);
public void increment() {
counter.incrementAndGet(); // Атомарна, без блокировок
}
public long getValue() {
return counter.get();
}
}
Преимущества AtomicLong:
- ✅ Атомарные операции
- ✅ Без явных блокировок (lock-free)
- ✅ Выше производительность чем synchronized
- ✅ CAS (Compare-And-Swap) операции
Когда volatile достаточно?
volatile подходит для простых операций чтения/записи:
public class FlagExample {
private volatile boolean shutdown = false;
public void stop() {
shutdown = true; // Атомарная операция сама по себе
}
public void run() {
while (!shutdown) { // Видит актуальное значение
doWork();
}
}
}
Здесь volatile достаточна, потому что запись булева значения — это атомарная операция на аппаратном уровне.
Таблица сравнения
| Характеристика | volatile | synchronized | AtomicLong |
|---|---|---|---|
| Видимость | ✅ | ✅ | ✅ |
| Атомарность простой записи | ✅ | ✅ | ✅ |
| Атомарность составных операций | ❌ | ✅ | ✅ |
| Производительность | Высокая | Низкая | Очень высокая |
| Lock-free | ✅ | ❌ | ✅ |
Выводы
- volatile ≠ атомарно — это разные концепции
volatileгарантирует видимость, но не защищает от race conditions- Для составных операций используй
synchronized,AtomicXxxилиReentrantLock AtomicLong/AtomicInteger— лучший выбор для счётчиков в многопоточной среде- Всегда думай о том, какие операции являются атомарными на аппаратном уровне