Получить доступ

Два потока одновременно вызывают incrementAndGet() у одного AtomicInteger. Что при этом происходит внутри и почему ни один инкремент не теряется?

MiddleМногопоточность
Коротко

CAS-цикл: прочитать значение, вычислить новое и записать, только если в памяти всё ещё старое (одна атомарная инструкция процессора). Проиграл гонку — повторить с новым значением. Блокировок нет, поток не засыпает.

  • Из двух одновременных CAS успешен ровно один
  • На x86 — инструкция lock cmpxchg
  • При сильной конкуренции растёт число повторов — LongAdder

А ещё Lock-free: система в целом прогрессирует, даже если отдельный поток задержан

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Начни с механизма: incrementAndGet не блокирует ничего, а крутит CAS-цикл. Поток читает текущее значение (пусть 5), вычисляет новое (6) и вызывает аппаратную инструкцию compare-and-swap: «если в памяти всё ещё 5 — положи 6, иначе не трогай». Инструкция атомарна на уровне процессора, поэтому из двух потоков успевает ровно один; проигравший видит, что CAS не прошёл, перечитывает уже 6, вычисляет 7 и повторяет попытку. Ни один инкремент не теряется именно потому, что запись условная — она привязана к тому значению, которое поток видел. Дальше назови свойство: это lock-free — поток не засыпает на мониторе, deadlock невозможен, но и гарантии для конкретного потока нет, он может проигрывать гонку несколько раз подряд. Закончи ценой: при сильной конкуренции цикл повторов и «пинг-понг» кэш-линии между ядрами делают один общий счётчик узким местом — тогда берут LongAdder, который разносит счёт по ячейкам. И упомяни ABA: CAS сравнивает значение, а не историю, поэтому A→B→A он не заметит; где это важно, нужен AtomicStampedReference.

Что хотят услышать

  • Механика CAS и цикла повторов.
  • Почему ни один инкремент не теряется.
  • Ограничения под высокой конкуренцией.

Частые ошибки

  • Считать, что atomic-классы «внутри синхронизированы» — поток не блокируется, а повторяет попытку.
  • Обещать, что CAS всегда быстрее synchronized: под высокой конкуренцией цикл повторов проигрывает.

Что спросят дальше

  • Что такое ABA-проблема и чем помогает AtomicStampedReference?
  • Почему при высокой конкуренции LongAdder обгоняет AtomicLong?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем