Является ли механизм CAS (Compare-And-Swap) универсальным решением для многопоточности?

«Является ли механизм CAS (Compare-And-Swap) универсальным решением для многопоточности?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, CAS — не "серебряная пуля". Это эффективный низкоуровневый примитив для атомарных операций, но у него есть ограничения, делающие его непригодным для всех сценариев.

Принцип работы: Операция атомарно сравнивает значение в памяти с ожидаемым и, если они совпадают, записывает новое значение.

Преимущества CAS (перед блокировками):

  • Отсутствие блокировок (lock-free): Потоки не приостанавливаются, а повторяют попытку при неудаче.
  • Исключение deadlock: Нет взаимных блокировок.
  • Высокая производительность при низкой и средней конкуренции.

Недостатки и ограничения:

  1. Проблема ABA: Поток видит, что значение A не изменилось, но на самом деле оно успело стать B и снова A. Это может нарушить логику некоторых алгоритмов. Решение — использование AtomicStampedReference или AtomicMarkableReference.
  2. Циклы при высокой конкуренции: При частых коллизиях множество потоков тратят CPU на повторные попытки ("гонка").
  3. Сложность составных операций: CAS работает с одной переменной. Для атомарного обновления нескольких связанных переменных требуется сложная логика (например, AtomicReference на объект-контейнер).

Пример CAS в AtomicInteger:

import java.util.concurrent.atomic.AtomicInteger;

AtomicInteger counter = new AtomicInteger(0);
// Попытка установить значение 1, только если текущее значение 0
boolean success = counter.compareAndSet(0, 1); // success = true
boolean failed = counter.compareAndSet(0, 2);  // failed = false (сейчас значение 1)

Вывод: CAS — отличный инструмент для простых атомарных обновлений (счётчики, флаги). Для сложных изменений состояния или при высокой конкуренции часто предпочтительнее использовать более высокоуровневые абстракции: synchronized, Lock или готовые классы из java.util.concurrent.