Какие способы синхронизации доступа к переменным существуют
Что проверяют
Различаете ли вы две проблемы: видимость изменений между потоками и атомарность составных операций. И умеете ли подобрать инструмент под задачу, а не ставить synchronized везде. На Android следом почти всегда спрашивают про корутины: чем Mutex отличается от обычной блокировки.
Как отвечать
Разложите способы от простого к сложному, с примерами на Kotlin:
@Volatile: запись одного потока гарантированно увидят другие. Атомарности не даёт:counter++на таком поле всё равно теряет инкременты;synchronized: монитор объекта, в Kotlin это функцияsynchronized(lock) { }или аннотация@Synchronized. Даёт и видимость, и взаимное исключение, повторный вход тем же потоком разрешён;ReentrantLockиReentrantReadWriteLock: то же плюсtryLockс таймаутом и раздельные блокировки для читателей и писателей. В Kotlin удобно черезwithLock;- атомики:
AtomicInteger,AtomicReference, операцииcompareAndSetиupdateAndGet. Без блокировок, хороши для счётчиков и замены одной ссылки; - потокобезопасные коллекции:
ConcurrentHashMap,CopyOnWriteArrayListдля списков, которые часто читают и редко меняют; - один поток: состояние меняется только на главном потоке или в
Dispatchers.Default.limitedParallelism(1). Часто это самый простой вариант; - корутины:
Mutexизkotlinx.coroutines.syncприостанавливает корутину, а не блокирует поток.MutableStateFlow.update { }меняет состояние атомарно через CAS.
Хороший финал: выбор зависит от того, что защищается. Одной переменной хватит атомика, инвариант из нескольких полей требует блокировки, а код на корутинах лучше строить на Mutex или одном потоке.
Где спотыкаются
Считают, что @Volatile делает операцию атомарной. Для цепочки «прочитать, изменить, записать» нужен атомик или блокировка.
Держат ReentrantLock через точку приостановки. Корутина может продолжиться на другом потоке, и unlock упадёт с IllegalMonitorStateException. С synchronized компилятор Kotlin такой код просто не пропустит.
Забывают, что Mutex не реентерабельный: вложенный withLock на том же мьютексе подвешивает корутину навсегда.