Middle+
Чӣ гуна метавон ҳамоҳангсозиро дар Kotlin бо истифода аз корутинҳо амалӣ кард?
sobes.tech AI
Ҷавоб аз AI
Сінхранізацыя ў Kotlin корутінах дасягаецца з дапамогай спецыяльных прымітываў і структур дадзеных з бібліятэкі kotlinx.coroutines.
Асноўныя падыходы:
-
Mutex
- Забяспечвае ўзаемнае выключэнне для абароны крытычных секцый кода.
- Корутына, якая спрабуе атрымаць Mutex, блакуецца, пакуль ён не будзе вызвалены.
- Мае функцыі
lock()іunlock(), а таксама больш ідыёматычныwithLock.
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.* val mutex = Mutex() var counter = 0 suspend fun increment() { mutex.withLock { counter++ } } suspend fun main() = coroutineScope { repeat(10_000) { launch { increment() } } println(counter) // Чакаем 10000 } -
Semaphore
- Абмяжоўвае колькасць корутин, якія могуць адначасова атрымаць доступ да рэсурсу або выканаць пэўны блок кода.
- Кіруе пулом дазволаў.
- Мае функцыі
acquire()іrelease(), а таксамаwithPermit.
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.* val semaphore = Semaphore(2) // Адначасова могуць працаваць 2 корутины suspend fun doLimitedWork(id: Int) { semaphore.withPermit { println("Корутына $id атрымала дазвол. Працуе...") delay(100) // Імітацыя працы println("Корутына $id вызваліла дазвол.") } } suspend fun main() = coroutineScope { repeat(5) { i -> launch { doLimitedWork(i) } } } -
Атамарныя аперацыі (з
kotlinx.coroutines.atomic)- Забяспечваюць патокабяспечныя аперацыі над праімтыўнымі тыпамі і спасылкамі.
- Выкарыстоўваюць нізка ўзроўневыя інструкцыі CPU (CAS - Compare-and-Swap).
- Падыходзяць для простых аперацый без відавочных блакіровак.
import kotlinx.coroutines.atomic.AtomicInt import kotlinx.coroutines.* val atomicCounter = AtomicInt(0) suspend fun atomicIncrement() { atomicCounter.incrementAndGet() } suspend fun main() = coroutineScope { repeat(10_000) { launch { atomicIncrement() } } println(atomicCounter.value) // Чакаем 10000 } -
Дзеляныя структуры дадзеных на дыспетчары з адным патокам
- Самы просты падыход. Запуск корутин на аднапотокавым кантэксце (
Dispatchers.Default.limitedParallelism(1)абоnewSingleThreadContext) гарантуе паслядоўнае выкананне кода, выключаючы гонкі дадзеных. Не з'яўляецца відавочным прымітывам сінхранізацыі, але забяспечвае сінхранізацыю шляхам серыялізацыі доступу.
import kotlinx.coroutines.* val mySingleThreadContext = newSingleThreadContext("SingleThread") var sharedData = mutableListOf<Int>() suspend fun addToSharedData(value: Int) { sharedData.add(value) // Бяспечна, бо выконваецца на адным патоку } suspend fun main() = withContext(mySingleThreadContext) { repeat(10_000) { launch { addToSharedData(it) } } println(sharedData.size) // Чакаем 10000 } - Самы просты падыход. Запуск корутин на аднапотокавым кантэксце (
-
Каналы
- Не з'яўляюцца прымітывамі сінхранізацыі ў чыстым выглядзе, але могуць выкарыстоўвацца для бяспечнай перадачы дадзеных паміж коруцінамі, што косвена вырашае праблемы сінхранізацыі доступу да перадаваемых дадзеных.
- Забяспечваюць спосаб перадачы патоку дадзеных з адной корутины ў іншую.
Выбар падыходу залежыць ад сцэнарыя выкарыстання. Mutex і Semaphore прапануюць класічныя механізмы блакіроўкі, атомарныя аперацыі эфектыўныя для простых атомарных абнаўленняў, а дыспетчар з адным патокам зручны, калі доступ да агульных дадзеных павінен быць строга паслядоўным. Каналы выкарыстоўваюцца для камунікацыі і каардынацыі, а не для прамой абароны агульных рэсурсаў.