Приходилось ли использовать атомики в Java
Что проверяют
Работали ли вы с многопоточностью руками и понимаете ли, что атомик решает узкую задачу, а не заменяет синхронизацию вообще.
Как отвечать
Классы из java.util.concurrent.atomic (AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference) дают атомарные операции над одной переменной без блокировок. Внутри лежит CAS, то есть инструкция процессора «сравни и замени»: поток читает текущее значение, вычисляет новое и меняет его только если никто не успел вмешаться, иначе повторяет попытку.
Что стоит назвать в ответе:
- зачем: обычный
count++это три операции и гонка,incrementAndGet()атомарен и виден другим потокам сразу, потому что поле внутри объявленоvolatile; - типичные применения: счётчики метрик, флаг «инициализация уже выполнена», ленивое создание объекта через
compareAndSet, накопление статистики; LongAdderиDoubleAdder: при высокой конкуренции они быстрееAtomicLong, так как разносят счёт по ячейкам и складывают их только при чтении. Для счётчиков нагрузки это стандартный выбор;AtomicReferenceсupdateAndGet: когда нужно атомарно заменить целый объект состояния.
Обязательно проговорите границу применимости: атомик защищает одну переменную. Если инвариант связывает два поля («списали со счёта A, зачислили на B»), нужен synchronized, ReentrantLock или транзакция, иначе состояние окажется рассогласованным.
private final AtomicInteger active = new AtomicInteger();
active.incrementAndGet();Где спотыкаются
Думают, что volatile заменяет атомик. volatile даёт видимость, но не атомарность инкремента.
Пишут цикл while (!ref.compareAndSet(old, new)) и забывают перечитать old внутри цикла, получая бесконечное повторение.
Не знают про проблему ABA: значение успело смениться и вернуться, CAS этого не заметит. Для таких случаев есть AtomicStampedReference.