Почему атомарную операцию нельзя прервать

Ответ

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

  1. Аппаратная поддержка: Процессоры предоставляют инструкции (например, CAS — Compare-And-Swap), которые гарантируют выполнение операции за один такт, без возможности вмешательства других потоков или прерываний.

  2. Гарантия целостности: Если бы операцию можно было прервать, это привело бы к состоянию гонки или повреждению данных. Например, при инкременте счетчика из двух потоков:

var counter = 0
// Без атомарности:
fun unsafeIncrement() {
    counter++ // Чтение -> изменение -> запись — не атомарно!
}

Атомарные операции (AtomicInteger, synchronized) исключают такие сценарии.

Ответ 18+ 🔞

Бля, ну слушай, тут такая тема интересная, как атомарные операции. Представь себе, что ты пытаешься налить себе чай, а тут тебя кто-то по руке бьёт — половина воды на стол, половина в кружку. Полный пиздец, да? Так вот, атомарная операция — это как раз про то, чтобы такого не было. Это такая неделимая штука, которая либо выполняется целиком, либо не выполняется вообще. Никаких «ой, я тут на полпути застрял».

Почему её нельзя прервать? Ну, во-первых, железо само помогает. Процессоры, эти хитрожопые чипы, имеют специальные команды, вроде CAS (Compare-And-Swap). Это как один молниеносный удар — бац, и всё сделано за один такт. Пока эта команда выполняется, никакой другой поток или прерывание не сунет свой нос, не скажет «а можно я?». Ёпта, это же святое!

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

Вот смотри, как это выглядит без защиты:

var counter = 0
// Без атомарности — пиздец нарисовался:
fun unsafeIncrement() {
    counter++ // По факту это три шага: прочитать -> изменить -> записать. И между ними могут влезть!
}

Представь: первый поток читает значение 0. Тут его вытесняют, и второй поток тоже успевает прочитать 0. Оба увеличивают его до 1 и записывают обратно. В итоге счётчик равен 1, хотя увеличивали его два раза! Вот это доверия ебать ноль ко всему происходящему.

Поэтому умные дядьки придумали AtomicInteger, synchronized и прочие штуки. Они эту операцию — чтение-изменение-запись — делают монолитной, неразрывной. Как будто ставишь табличку «Не влезай, убьёт!». Никто не сможет вклиниться и всё испортить. Вот и вся магия, чувак. Без этого в многопоточке — один сплошной чих-пых тебя в сраку.