Для чего используются классы `Atomic*` в Java?

«Для чего используются классы `Atomic*` в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Назначение: Классы из пакета java.util.concurrent.atomic (например, AtomicInteger, AtomicLong, AtomicReference, AtomicBoolean) предоставляют атомарные операции над одиночными переменными в многопоточной среде без использования явных блокировок (synchronized).

Проблема, которую они решают:

// Непотокобезопасный инкремент (возможна race condition)
int counter = 0;
counter++; // Операция «чтение-изменение-запись» не атомарна.

Решение с AtomicInteger:

import java.util.concurrent.atomic.AtomicInteger;

AtomicInteger atomicCounter = new AtomicInteger(0);

// Атомарный инкремент. Гарантированно вернет правильное значение.
int newValue = atomicCounter.incrementAndGet(); // Аналог ++counter

Ключевые особенности и преимущества:

  • Атомарность: Операции чтения-изменения-записи выполняются как единое неделимое действие.
  • Отсутствие блокировок (lock-free): Реализация основана на CAS (Compare-And-Swap) — низкоуровневой процессорной инструкции, которая более эффективна, чем synchronized, в условиях высокой конкуренции.
  • Волатильность: Все операции с Atomic-классами гарантируют happens-before отношения, аналогичные volatile переменным.

Типичные сценарии использования:

  • Счетчики в многопоточной среде.
  • Флаги состояния (AtomicBoolean).
  • Простые агрегаты или ссылки, требующие атомарного обновления (AtomicReference).
  • База для реализации неблокирующих алгоритмов и структур данных.

Важное ограничение: Atomic-классы обеспечивают атомарность для одной переменной. Для согласованного изменения группы переменных необходимы другие механизмы (например, synchronized или Lock).