Что такое ABA-проблема в алгоритмах на CAS?
CAS сравнивает только текущее значение, а не историю: A → B → A выглядит как «ничего не менялось». В lock-free структурах со ссылками это ломает данные (узел удалили и переиспользовали).
- Решение в Java — AtomicStampedReference: ссылка плюс счётчик версии
- AtomicMarkableReference — ссылка плюс флаг
- Для счётчиков ABA безобидна
А ещё Сборщик мусора смягчает проблему: адрес живого объекта не переиспользуется
Подробно
Для счётчиков это безобидно, но в структурах данных со ссылками может быть фатально: узел удалили, память переиспользовали, и ссылка снова указывает на тот же адрес — CAS решит, что ничего не произошло, и порушит структуру. Штатное решение в Java — AtomicStampedReference, где вместе со ссылкой хранится версия-метка, увеличивающаяся при каждом изменении; сравнение идёт по паре, поэтому возврат к прежнему значению обнаруживается. Есть и AtomicMarkableReference с одним булевым флагом для более простых случаев. Полезно упомянуть, что сам CAS реализован аппаратной инструкцией процессора и лежит в основе всех атомарных классов и большей части java.util.concurrent.
Что хотят услышать
- Суть проблемы и пример.
- Версионирование как решение.
Частые ошибки
- Считать ABA чисто теоретической проблемой во всех случаях.
- Путать ABA с обычным конфликтом при высокой конкуренции.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Два потока одновременно выполняют CAS по одному адресу, и оба завершаются успешно
- ✗CAS зацикливается, потому что значение постоянно меняется
- ✗Компилятор переупорядочивает операции вокруг CAS
- ✓Значение сменилось A → B → A, и CAS не замечает изменений
Что спросят дальше
- Как устроен AtomicStampedReference?
- Почему при высокой конкуренции цикл CAS деградирует?
Разбор темы
- volatile, атомарность и CAS
Разница видимости и атомарности, atomic-классы, compare-and-swap и ABA, контеншн и LongAdder.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.