С чем связаны монитор, lock, mutex и подобные механизмы?
Что проверяют
Понимаете ли вы, что все эти слова про одно свойство, взаимное исключение, и чем отличаются конкретные реализации на JVM и в корутинах. Для Android важна вторая половина: умеете ли вы обходиться без блокировок там, где хватает ограничения доступа одним потоком.
Как отвечать
Начните с задачи: критическую секцию в один момент времени должен выполнять один поток, иначе получаем гонку данных. Дальше по механизмам:
- монитор есть у каждого объекта на JVM.
synchronizedи@Synchronizedзахватывают его, он реентрантный, аwaitиnotifyработают на том же мониторе; ReentrantLockдаёт то же исключение, но сtryLock, таймаутом, прерываемым захватом, честным режимом и несколькими условиями. Освобождение ручное и только вfinally;- мьютекс в терминах операционной системы это примитив с одним владельцем. В корутинах Kotlin есть свой
Mutex, он не блокирует поток, а приостанавливает корутину; - рядом стоят
Semaphoreпро счётчик разрешений и атомарные типы вместе с@Volatileпро видимость без блокировки.
private val mutex = Mutex()
suspend fun add(item: Item) = mutex.withLock { items += item }Для Android добавьте практику: состояние экрана обычно не защищают замками, а держат в одном потоке через главный диспетчер и неизменяемые снимки в StateFlow.
Где спотыкаются
Считают, что синхронизация только про атомарность. Она ещё и про видимость: без неё другой поток может долго читать устаревшее значение. Обратное тоже верно, одного @Volatile мало для инкремента, потому что чтение и запись там разные операции.
Второе: берут замок не по тому объекту. Синхронизация по изменяемому полю, по текущему экземпляру публичного класса или по строковому литералу либо не даёт исключения вовсе, либо делит один замок со всем приложением.
Третье: держат блокировку слишком долго и захватывают вложенно в разном порядке. Первое на главном потоке превращается в зависший интерфейс и жалобу системы на неотвечающее приложение, второе даёт классический дедлок, который на устройстве пользователя воспроизводится раз в месяц.