Ответ
Нет. Ключевое слово volatile не гарантирует атомарность составных операций, таких как инкремент (i++).
- Что дает
volatile: Гарантирует видимость (visibility) изменений переменной между потоками. Когда один поток записывает значение вvolatile-переменную, это изменение немедленно становится видимым для всех других потоков. - Почему инкремент небезопасен: Операция
counter++— это не одна, а три операции (read-modify-write):- Чтение текущего значения.
- Увеличение значения на 1.
- Запись нового значения. Два потока могут прочитать одно и то же старое значение, инкрементировать его и записать, в результате чего одно увеличение будет потеряно.
Потокобезопасные альтернативы:
-
Классы из пакета
java.util.concurrent.atomic(наиболее эффективно):import java.util.concurrent.atomic.AtomicInteger; AtomicInteger atomicCounter = new AtomicInteger(0); atomicCounter.incrementAndGet(); // Атомарный инкремент -
Синхронизация (
synchronized):public class Counter { private int counter = 0; public synchronized void increment() { counter++; } } -
Использование
ReentrantLock:import java.util.concurrent.locks.ReentrantLock; public class Counter { private int counter = 0; private final ReentrantLock lock = new ReentrantLock(); public void increment() { lock.lock(); try { counter++; } finally { lock.unlock(); } } }volatileидеально подходит для флагов или переменных, где операция записи является простым присваиванием (flag = true), а не зависит от предыдущего значения.