Материал проходит вычитку — возможны неточности.
Урок 98 из 118

Compare-and-swap

Счётчик обработанных байтов недосчитывал: несколько воркеров прибавляли одновременно, и часть записей терялась. Миша переписал инкремент на atomic.Add, и после ночного прогона счётчик впервые сошёлся с S3.

Главная мысль

CAS — «запиши новое значение, только если там всё ещё старое»: операция возвращает, удалась ли замена, и на ней строят циклы обновления без блокировок.

Что такое CAS

Go

CAS атомарно проверяет текущее значение и, если оно совпало с ожидаемым, заменяет его. Это «если-затем-записать» как одна неделимая операция — то, чего не хватало обычным if n == 0 { n = 1 }, где между проверкой и записью вклинивалась другая горутина.

CAS-loop

Если CAS не удался, значение тем временем изменил кто-то другой. Стандартный паттерн — повторить:

for {
    old := n.Load()
    new := old * 2
    if n.CompareAndSwap(old, new) {
        return new
    }
    // не вышло: кто-то изменил — перечитываем и пробуем снова
}

Цикл «прочитал — посчитал — попробовал записать» с повтором и есть CAS-loop. При умеренной конкуренции он быстрее мьютекса: нет блокировок, нет очередей — только редкие повторы при столкновениях.

Где живёт CAS

Add — отдельная аппаратная атомарная read-modify-write операция (на amd64 это инструкция LOCK XADD), а не цикл CAS под капотом. Явный CAS нужен, когда обновление не сводится к «прибавить»: удвоить, обменять местами, записать максимум. Любое «прочитал — вычислил новое из старого» на общей переменной — кандидат на CAS-loop.

В следующем уроке

Вы узнаете:

  • когда CAS-loop дешевле мьютекса
  • как устроен lock-free стек на CAS
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Между Load и CompareAndSwap значение прошло путь A → B → A. Что сделает CAS?

Вопрос 2 из 3

Почему «if Load == 0 { Store }» не заменяет CAS?

Вопрос 3 из 3

Для чего ABA-проблема действительно опасна?

Итоги

CAS — атомарная «если старое, то новое»; CAS-loop — неблокирующее обновление с повтором при столкновениях. Add — отдельный аппаратный примитив (LOCK XADD), а не цикл CAS. Основа lock-free счётчиков и структур.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки