В Android-разработке существует множество механизмов для потокобезопасной работы с данными, каждый со своими особенностями и сценариями применения.
Более гибкая альтернатива synchronized
с возможностью:
val lock = ReentrantLock()
fun safeIncrement() {
lock.lock()
try {
// Критическая секция
counter++
} finally {
lock.unlock() // Всегда в finally!
}
}
Оптимизация для read-heavy сценариев:
val rwLock = ReentrantReadWriteLock()
fun readData(): String {
rwLock.readLock().lock()
try {
return sharedData
} finally {
rwLock.readLock().unlock()
}
}
Для простых атомарных операций без полной блокировки:
val atomicCounter = AtomicInteger(0)
fun increment() {
atomicCounter.incrementAndGet()
// Или сложные операции:
atomicCounter.updateAndGet { it + 2 }
}
Для асинхронного кода в корутинах:
val mutex = Mutex()
var sharedData = 0
suspend fun safeUpdate() {
mutex.withLock {
sharedData++ // Приостанавливает, а не блокирует поток
}
}
Готовые реализации из java.util.concurrent
:
ConcurrentHashMap
CopyOnWriteArrayList
BlockingQueue
и ее реализацииval concurrentMap = ConcurrentHashMap<String, Int>()
concurrentMap.compute("key") { _, v -> (v ?: 0) + 1 }
Для реактивного подхода:
val sharedFlow = someFlow
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = 0
)
Для гарантии видимости изменений между потоками (но не атомарности):
@Volatile
var flag = false
Оптимизированный вариант для ленивой инициализации:
val lazyValue: SomeType by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
SomeType()
}
Гранулярность блокировки:
Тип операций:
Контекст выполнения:
Производительность:
В Android-разработке выбор механизма синхронизации зависит от конкретного сценария - от атомарных операций и потокобезопасных коллекций для простых случаев до сложных систем с комбинацией Mutex, Flow и кастомных блокировок для высоконагруженных приложений.