Middle+
Kotlinде корутиндерди колдонуп синхрондоштурууну кантип ишке ашырууга болот?
sobes.tech AI
AIден жооп
Котлин корутиндеринде синхрондаштыруу 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тен)- Туура иштөө үчүн потокко коопсуз операцияларды primitives жана шилтемелер үстүндө камсыздайт.
- төмөн деңгээлдеги 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колдонуу бир тармактуу контекстте корутиндерди иштетүү, маалыматтардын катарлаш иштешин камсыз кылат, бул гонкалардын алдын алат. Бул ачык синхрондаштыруу primitive эмес, бирок сериализация аркылуу синхрондуулук камсыз кылат.
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 күтүлүүдө } - эң жөнөкөй ыкма.
-
Channels
- Ачуу синхрондаштыруу primitive эмес, бирок корутиндер арасында маалыматтарды коопсуз өткөрүү үчүн колдонулушу мүмкүн, бул косвенно жеткиликтүү маалыматтарга жетүүнүн проблемаларын чечет.
- Бир корутинадан экинчи корунага маалымат агымын өткөрүүчү ыкма.
Тандоо колдонуу сценарийине жараша болот. Mutex жана Semaphore классикалык блоктоо механизмдерин камсыздайт, Atomic операциялар жөнөкөй атомардык жаңыртуулар үчүн эффективдүү, ал эми бир-тайптуу диспетчер катуу тартипте жалпы маалыматка жетүүнү талап кылганда ыңгайлуу. Channels коммуникация жана координация үчүн колдонулат, түз эле жалпы ресурстарды коргоо үчүн эмес.