TGViewer
Android under the hood Android under the hood @android_under_the_hood · 1.53K subscribers
Post #86 3.23K
Начнём с того, что даже простое чтение переменной может вызвать проблемы в многопоточных программах, так как у каждого процессорного ядра есть свои кэши, поэтому для актуального чтения используется @Volatile.

Но что если нам нужно прочитать какое-то значение, пройтись в when операторе, а потом записать новое, можно конечно попробовать сделать это через @Volatile:

@Volatile var _state: Int

when(_state) {
NONE -> _state = PENDING
...
}


Но проблема в том, что может произойти ситуация когда поток X прочитает актуальное значение, а в этот момент поток Y запишет другое, что приведет к нелогичным данным.

Глянем решение с compareAndSet(), пример взят из исходников StateFlow:

val _state = atomic(0)

while(true) {
val state = _state.value
when(state) {
NONE -> if (_state.compareAndSet(state, PENDING)) break
...
}
}


Метод compareAndSet() под капотом реализован процессорной инструкцией, эта инструкция выполняется атомарно и следовательно не нуждается в синхронизации между потоками, работает она следующим образом:

1) читает актуальное значение переменной _state из памяти как это делает @Volatile
2) сравнивает актуальное значение с текущим state, которое как мы уже знаем может быть неактуальным
3) если значение актуально, записывает новое PENDING и возвращает true
4) если значение неактуально возвращает false

Когда поток Y запишет новое значение, поток X начнёт выполнять метод compareAndSet(), который вернёт false, так как данные неактуальны, далее начнётся новая итерация цикла, это будет продолжаться до тех пор пока на потоке X не появятся актуальные данные и только когда это произойдёт запишутся новые.

P.S. Использование бесконечного цикла с инструкцией compareAndSet() это нормальная практика, применяется много где: начиная с корутин и заканчивая Android SDK.

Пишите ваше мнение в комментах и всем хорошего кода!
  • 👍 30
  • 🔥 6
  • 👏 5
More from @android_under_the_hood
  1. Oct 4, 2026Всем привет, хочу поделиться проектом, который запустил 1 октября — ЗдесьЯ. Это цифровая с…
  2. Oct 2, 2026Kotlin lambdas, часть I. До версии Kotlin 2.0 лямбды компилировались в анонимные классы, р…
  3. Sep 27, 2026Делегат свойства в Kotlin. В Kotlin есть конструкция, которой нет в JVM: var name by NameD…
  4. Sep 23, 2026val vs var под капотом. На уровне Kotlin все просто: val x = 10 var y = 20 y = 30 // компи…
  5. Sep 20, 2026Возвращение Прошло уже полгода с последней записи на канале. За это время в моей жизни про…
  6. Feb 5, 2026Пару фактов о Go, часть II. 4) Вместо Kotlin Nullability указатели как в С/C++, то есть об…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →