Middle+
Kotlin-də koroutinlər istifadə edərək sinxronizasiyanı necə həyata keçirmək olar?
sobes.tech Süni İntellekt
AI-dan cavab
Kotlin korutinlərində sinxronizasiya kotlinx.coroutines kitabxanasından xüsusi primitive və məlumat strukturları vasitəsilə həyata keçirilir.
Əsas yanaşmalar:
-
Mutex
- Kritik kod bölmələrini qorumaq üçün qarşılıqlı istisna təmin edir.
- Mutex əldə etməyə çalışan korutin, sərbəst buraxılana qədər bloklanır.
lock()vəunlock()funksiyalarına əlavə olaraq, daha çox idiomatikiwithLockfunksiyası var.
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) // Gözlənilir 10000 } -
Semaphore
- Eyni anda resursa giriş edə biləcək korutinlərin sayını məhdudlaşdırır.
- İcazə hovuzunu idarə edir.
acquire()vərelease()funksiyalarına əlavə olaraq,withPermitvar.
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.* val semaphore = Semaphore(2) // Eyni zamanda 2 korutin işləyə bilər suspend fun doLimitedWork(id: Int) { semaphore.withPermit { println("Korutin $id icazə aldı. İşləyir...") delay(100) // İşin təqlidi println("Korutin $id icazəni sərbəst buraxdı.") } } suspend fun main() = coroutineScope { repeat(5) { i -> launch { doLimitedWork(i) } } } -
Atomik əməliyyatlar (kotlinx.coroutines.atomic-dən)
- İplik təhlükəsiz əməliyyatlar təmin edir, primitive tiplər və referanslar üzərində.
- Aşağı səviyyəli CPU əmrlərindən (CAS - Compare-and-Swap) istifadə edir.
- Sadə əməliyyatlar üçün uyğundur, açıq bloklamalar olmadan.
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) // Gözlənilir 10000 } -
Tək iplikli dispatcher-də paylaşılan məlumat strukturları
- Ən sadə yanaşma. Korutinləri tək iplikli kontekstdə işlətmək (
Dispatchers.Default.limitedParallelism(1)və yanewSingleThreadContext) kodun ardıcıl icrasını təmin edir, məlumatların yarışmasını istisna edir. Bu, açıq sinxronizasiya primitive deyil, lakin girişin seriyalaşdırılması ilə sinxronizasiya təmin edir.
import kotlinx.coroutines.* val mySingleThreadContext = newSingleThreadContext("SingleThread") var sharedData = mutableListOf<Int>() suspend fun addToSharedData(value: Int) { sharedData.add(value) // Eyni iplikdə icra olunduğu üçün təhlükəsiz } suspend fun main() = withContext(mySingleThreadContext) { repeat(10_000) { launch { addToSharedData(it) } } println(sharedData.size) // Gözlənilir 10000 } - Ən sadə yanaşma. Korutinləri tək iplikli kontekstdə işlətmək (
-
Kanalardan istifadə
- Əsasən sinxronizasiya primitive deyil, lakin məlumatların təhlükəsiz ötürülməsi üçün istifadə oluna bilər, bu da məlumatların girişinə nəzarəti dolayı yolla həll edir.
- Bir korutindən digərinə məlumat axını ötürmək üçün vasitədir.
İstifadə ssenarisinə görə yanaşma seçimi dəyişir. Mutex və Semaphore klassik kilidləmə mexanizmləri təqdim edir, Atomik əməliyyatlar sadə atomik yeniləmələr üçün effektivdir, tək iplikli dispatcher isə məlumatlara girişin ardıcıl olmasını tələb etdiyində əlverişlidir. Kanallar isə kommunikasiya və koordinasiya üçün istifadə olunur, birbaşa ümumi resursların qorunması üçün deyil.