← Назад к вопросам

Обеспечивает ли volatile атомарность операций

2.7 Senior🔥 121 комментариев
#JVM и управление памятью#Многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Обеспечивает ли volatile атомарность операций

Короткий ответ

Нет, volatile НЕ обеспечивает атомарность операций. Volatile гарантирует только видимость (visibility) изменений между потоками, но не делает операции неделимыми (atomic).

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

Включение volatile в Java обеспечивает:

  1. Видимость (Visibility) — изменения одного потока немедленно видны другим потокам
  2. Упорядочение памяти (Memory Ordering) — предотвращает инструкции из переупорядочения до/после доступа к volatile переменной
  3. Запрет оптимизаций — JIT компилятор не будет кэшировать значение в регистре

Почему volatile НЕ атомарный

Атомарность означает, что операция выполняется как неделимое целое без вмешательства других потоков. Например:

private volatile long counter = 0;

// Это НЕ атомарная операция!
counter++; // Эквивалентно: counter = counter + 1

Эта операция состоит из 3 шагов:

  1. Прочитать значение counter
  2. Прибавить 1
  3. Записать результат обратно

Между шагами другой поток может прочитать/изменить counter. Пример race condition:

public class VolatileNotAtomic {
    private volatile int counter = 0;
    
    public void increment() {
        counter++; // Race condition!
    }
    
    public static void main(String[] args) throws InterruptedException {
        VolatileNotAtomic obj = new VolatileNotAtomic();
        
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) obj.increment();
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) obj.increment();
        });
        
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        
        System.out.println(obj.counter); // Может быть < 2000!
    }
}

Когда volatile достаточно

Volatile подходит только для простых присваиваний значений:

private volatile boolean running = true;
private volatile String status = "IDLE";

// Безопасно: простое присваивание
running = false;
status = "PROCESSING";

Эти операции атомарны на уровне памяти JVM для примитивов и ссылок.

Решение для атомарных операций

Для операций, требующих атомарности, используй:

// 1. AtomicInteger, AtomicLong, AtomicReference
private AtomicInteger counter = new AtomicInteger(0);
public void increment() {
    counter.incrementAndGet(); // Атомарно
}

// 2. synchronized блок
private int counter = 0;
public synchronized void increment() {
    counter++; // Атомарно
}

// 3. ReentrantLock
private final Lock lock = new ReentrantLock();
private int counter = 0;
public void increment() {
    lock.lock();
    try {
        counter++;
    } finally {
        lock.unlock();
    }
}

Заключение

Volatile — легковесный инструмент для видимости памяти, но никогда не используй его для операций типа increment, decrement, check-then-act. Для реальной атомарности нужны Atomic* классы или синхронизация.