Атомарность: операция целиком или никак

28 октября 2026 · ~8 мин чтения

конкурентность базы-данных надёжность программирование

Атомарность

Атомарность — свойство операции, при котором для наблюдателя она выглядит неделимой: либо произошло всё предусмотренное изменение, либо не произошло ничего. В многопоточной программе это также означает, что конкурентные операции не могут вклиниться в середину защищённого действия.

История

Представление об атомарной операции появилось вместе с развитием вычислительных систем, где несколько процессов могли одновременно работать с общей памятью. Уже ранние многопроцессорные компьютеры требовали согласовывать доступ к общим данным: простая команда программы могла состоять из нескольких машинных шагов, а другой процессор — изменить данные между ними. Поэтому производители процессоров добавляли специальные атомарные инструкции, а операционные системы и языки программирования развивали средства синхронизации.

Параллельно атомарность стала важным свойством транзакций баз данных. В 1970-х годах Джим Грей систематизировал основы транзакционной обработки; в 1983 году он вместе с Андреасом Ройтером опубликовал работу о принципах проектирования систем обработки транзакций. Отсюда выросла известная группа свойств ACID: atomicity, consistency, isolation, durability — атомарность, согласованность, изоляция и долговечность.

В современных языках, включая C++, Java, Rust и Python, способы получить атомарное поведение различаются. Стандарт C++11 (2011) формализовал модель памяти и библиотеку атомарных типов; Java предоставляет классы java.util.concurrent.atomic; Rust включает атомарные типы в стандартную библиотеку. Важно не смешивать: атомарность транзакции базы, атомарная операция процессора и атомарность бизнес-действия — родственные идеи, но разные гарантии.

Что это такое

Представь, что в общем счётчике хранится число 10, а два потока одновременно хотят прибавить по единице. Наивная операция counter += 1 часто состоит из трёх шагов: прочитать число, вычислить новое значение, записать его. Оба потока могут прочитать 10, оба вычислить 11, а затем записать 11. Итог — 11 вместо 12. Каждый поток выполнил свою команду, но совокупное изменение потеряло обновление.

Атомарное увеличение не позволяет разделить действие на наблюдаемые части. Система гарантирует, что конкурирующие вызовы будут упорядочены так, будто сначала целиком выполнился один, потом другой. Тогда результатом станет 12. Это пример атомарности относительно конкретной переменной и конкретной операции; он не обещает, что целая последовательность из десятка команд автоматически станет неделимой.

В базах данных атомарность транзакции отвечает на другой вопрос: если перевод состоит из списания со счёта A и зачисления на счёт B, не останется ли система после сбоя в состоянии «списали, но не зачислили»? Транзакция группирует изменения: фиксация делает их видимыми как единый результат, а откат отменяет незавершённую группу.

Атомарность vs изоляция. Атомарность — «всё или ничего» для изменения. Изоляция — насколько параллельные транзакции скрыты друг от друга и какие результаты их взаимодействия допустимы. Транзакция может быть атомарной, но при недостаточной изоляции всё равно столкнуться с аномалиями чтения.

Атомарность vs долговечность. Успешно зафиксированная операция атомарна, если она не оставляет частичного состояния. Долговечность отвечает, переживёт ли зафиксированный результат отключение питания или перезапуск. Это отдельные гарантии.

Аналогии из жизни

Банковский перевод. Перевести сто рублей — значит одновременно отразить списание и зачисление. Аналогия хорошо показывает, почему половина операции неприемлема. Где ломается: техническая транзакция обычно охватывает только одну базу или систему. Между двумя независимыми банками могут использоваться отдельные подтверждения, компенсации и задержки; мгновенного общего «переключателя» может не быть.

Дверь с защёлкой. Пока дверь открыта или закрыта, наблюдатель не должен видеть её в невозможном промежуточном состоянии «наполовину заперта». Это напоминает неделимое переключение состояния. Где ломается: многие реальные физические механизмы как раз проходят через промежуточные положения; аналогия описывает желаемое наблюдаемое поведение, а не устройство программной блокировки.

Пакет документов. Сотрудник принимает папку только после проверки всех обязательных листов; иначе возвращает её целиком. Это похоже на фиксацию всей транзакции или её отмену. Где ломается: база данных может на время транзакции хранить внутренние промежуточные изменения. Важно, что конкурирующие наблюдатели не видят их как уже завершённый результат, а не то, что промежуточных вычислений физически нет.

Как это работает

Для атомарности есть несколько распространённых механизмов. На уровне процессора существуют специальные инструкции, например compare-and-swap (сравнить и заменить): «замени значение, только если оно всё ещё равно ожидаемому». Процессор выполняет проверку и замену как одну атомарную операцию. Если значение изменилось, программа повторяет попытку с новым наблюдаемым состоянием.

Упрощённо это выглядит так:

повторять:
    старое = прочитать значение
    новое = вычислить(старое)
пока compare_and_swap(значение, старое, новое) неуспешен

Для составных действий часто используют mutex (мьютекс, взаимное исключение) или другой lock (блокировку). Поток захватывает блокировку перед критической секцией — участком, который работает с общим состоянием, — выполняет все связанные шаги и освобождает её. Остальные участники ждут. Важно защищать одной и той же блокировкой весь цикл «прочитать → проверить → изменить → сохранить», а не отдельные строки по отдельности. Иначе между проверкой и изменением может вклиниться другой поток.

В базе данных транзакция начинается, выполняет набор запросов, а затем вызывает COMMIT (зафиксировать) или ROLLBACK (откатить). СУБД может вести журнал изменений, хранить версии страниц или использовать другие механизмы восстановления. При сбое она определяет, какие транзакции успели зафиксироваться, и приводит хранилище к допустимому состоянию. Конкретные гарантии зависят от базы и настроек: например, «успех» может означать разное с точки зрения подтверждения записи на физический носитель.

У атомарности есть границы. Операция над одним атомарным числом не делает автоматически атомарными два разных числа. Блокировка помогает лишь тогда, когда все участники соглашения её соблюдают. Транзакция одной базы обычно не включает автоматически внешний HTTP-запрос, отправку письма или запись в другую независимую базу. Для распределённых процессов приходится проектировать протоколы согласования, повторов и компенсаций.

Где встречается в обычной жизни

Где встречается в IT и бизнесе

Кто пользуется

Атомарные операции есть в процессорах и стандартных библиотеках популярных языков, поэтому ими пользуются практически все разработчики многопоточных систем. Транзакции с атомарными гарантиями поддерживают, например, PostgreSQL, MySQL/InnoDB и SQLite. Это не отдельный продукт с определённым числом пользователей, а базовое свойство вычислений и хранения данных; достоверную единую цифру масштаба для него назвать нельзя.

Альтернативы и конкуренты

Когда НЕ стоит использовать

Связанные понятия

Литература и источники

Где встретилось у меня

При разборе параллельной обработки и сохранения общего состояния в программном компоненте обсуждалось, как не допустить гонки между чтением, проверкой и записью данных. Атомарность всплыла как требование выполнять такой цикл целиком, а не защищать отдельные шаги.

Краткое резюме