Sobes.tech
Middle+

Kotlin'de koroutinler kullanarak senkronizasyon nasıl gerçekleştirilebilir?

sobes.tech yapay zeka

AI'dan gelen yanıt

Kotlin coroutinelerinde senkronizasyon, kotlinx.coroutines kütüphanesinden özel primitive ve veri yapıları kullanılarak sağlanır.

Ana yaklaşımlar:

  1. Mutex

    • Kritik kod bölümlerini korumak için karşılıklı dışlama sağlar.
    • Mutex'i almak isteyen coroutine, serbest bırakılana kadar bloklanır.
    • lock() ve unlock() fonksiyonlarına ek olarak, daha idiomatik olan withLock fonksiyonuna sahiptir.
    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) // Beklenen 10000
    }
    
  2. Semaphore

    • Aynı anda erişebilecek coroutine sayısını veya belirli bir kod bloğunu çalıştırabilecek coroutine sayısını sınırlar.
    • İzin havuzunu yönetir.
    • acquire() ve release() fonksiyonlarına ek olarak withPermit sağlar.
    import kotlinx.coroutines.sync.Semaphore
    import kotlinx.coroutines.sync.withPermit
    import kotlinx.coroutines.*
    
    val semaphore = Semaphore(2) // Aynı anda 2 coroutine çalışabilir
    
    suspend fun doLimitedWork(id: Int) {
        semaphore.withPermit {
            println("Coroutine $id izin aldı. Çalışıyor...")
            delay(100) // Çalışmayı taklit et
            println("Coroutine $id izin verdi.")
        }
    }
    
    suspend fun main() = coroutineScope {
        repeat(5) { i ->
            launch {
                doLimitedWork(i)
            }
        }
    }
    
  3. Atomik işlemler (kotlinx.coroutines.atomic'den)

    • Primitif tipler ve referanslar üzerinde thread-safe işlemler sağlar.
    • Düşük seviyeli CPU talimatlarını (CAS - Compare-and-Swap) kullanır.
    • Açık kilitler olmadan basit işlemler için uygundur.
    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) // Beklenen 10000
    }
    
  4. Tek iş parçacıklı dağıtıcı üzerinde paylaşılan veri yapıları

    • En basit yaklaşım. Kodun sıralı yürütülmesini garanti eden tek iş parçacıklı bağlamda (Dispatchers.Default.limitedParallelism(1) veya newSingleThreadContext) çalıştırmak, yarış koşullarını önler. Açık bir senkronizasyon primitive değildir, ancak erişimi seri hale getirerek senkronizasyon sağlar.
    import kotlinx.coroutines.*
    
    val mySingleThreadContext = newSingleThreadContext("SingleThread")
    var sharedData = mutableListOf<Int>()
    
    suspend fun addToSharedData(value: Int) {
        sharedData.add(value) // Güvenli, çünkü tek bir iş parçacığında çalışıyor
    }
    
    suspend fun main() = withContext(mySingleThreadContext) {
        repeat(10_000) {
            launch {
                 addToSharedData(it)
            }
        }
        println(sharedData.size) // Beklenen 10000
    }
    
  5. Kanallar

    • Kendisi doğrudan senkronizasyon primitive değildir, ancak koroutinler arasında güvenli veri iletimi için kullanılabilir, bu da iletilen verilere erişimdeki senkronizasyon sorunlarını dolaylı olarak çözer.
    • Bir koroutinden diğerine veri akışını iletmek için bir yol sağlar.

Kullanım senaryosuna bağlı olarak yaklaşım seçilir. Mutex ve Semaphore klasik kilitleme mekanizmaları sağlar, Atomik işlemler basit atomik güncellemeler için etkilidir, ve tek iş parçacıklı dağıtıcı, paylaşılan verilere erişimin kesinlikle sıralı olması gerektiğinde kullanışlıdır. Kanallar ise iletişim ve koordinasyon için kullanılır, doğrudan paylaşılan kaynakların korunması için değil.