Coroutines — temel kavramlar, Kotlin'de Job ve Dispatchers

Yazar: IT Sectr Yayınlanma: 2026-03-16 Okuma süresi: 8 dk

Coroutines (korutinler), kotlinx.coroutines kütüphanesi aracılığıyla kullanılabilen, Kotlin'de asenkron programlama için hafif thread'lerdir. JetBrains Kotlin Documentation, 2026'ya göre, Coroutines, geleneksel Thread'lerin aksine, bir thread'i bloke etmeden fonksiyon yürütmeyi askıya alabilir. Korutinler sınırlı bir thread havuzunda çalışır ve bu da onları yerel thread'lerden bin kat daha hafif yapar. Kotlin Coroutines, Android Jetpack, Retrofit, Room ve Android ekosisteminin diğer popüler kütüphaneleriyle tamamen entegredir.

Önemli Noktalar

  • Coroutines — blokajsız asenkron kod için hafif Kotlin thread'leri
  • suspend fonksiyonu — bir thread'i bloke etmeden duraklayıp devam edebilen fonksiyon
  • Dispatcher korutin yürütmesi için thread havuzunu belirler
  • Job — iptal desteği ve durum takibi ile korutin tanımlayıcısı
  • CoroutineScope korutinlerin yaşam döngüsünü ve tamamlandıklarında iptal edilmelerini yönetir

Kotlin Korutinleri Nedir

Coroutines, kotlinx.coroutines kütüphanesinde uygulanan Kotlin'de bir asenkron programlama mekanizmasıdır. İşletim sistemi thread'lerinin aksine, korutinler belirli bir thread'e bağlı değildir: bir thread'de askıya alınabilir ve başka bir thread'de devam edebilir. Tek bir thread, minimum ek yük ile aralarında geçiş yaparak binlerce korutini yürütebilir.

Korutinler, Kotlin 1.3'te (2018) deneysel bir özellik olarak ortaya çıktı ve Kotlin 1.5'te (2021) kararlı hale geldi. Coroutines, callback hell sorununu async/await benzeri şekilde çözer, ancak daha zengin bir API sağlar: kanallar (Channel), Flow, Job hiyerarşisinde istisna yönetimi ve Android Lifecycle ile doğrudan entegrasyon.

JetBrains'e (2025) göre, her korutin yaklaşık 100 bayt bellek tüketirken, yerel bir thread 1+ MB tüketir. Bu, OutOfMemoryError riski olmadan tek bir uygulamada milyonlarca korutin çalıştırmaya olanak tanır. Korutinlerin hafifliği, onları Android'de asenkronluk için tercih edilen araç haline getirir.

Korutinlerin İçeride Nasıl Çalıştığı

Her Kotlin korutini, Continuation Passing Style (CPS) kullanılarak bir durum makinesine derlenir. Derleyici, her suspend fonksiyonuna gizli bir Continuation parametresi ekler. Continuation, devam noktasını ve tüm yerel değişkenleri içerir. Bir korutin askıya alındığında, çalışma zamanı Continuation'ı kaydeder ve devam ettiğinde, Dispatcher havuzundaki herhangi bir uygun thread'de geri yükler.

suspend Fonksiyonları: Duraklatma ve Devam Etme

suspend, bir fonksiyonu askıya alınabilir olarak işaretleyen bir Kotlin anahtar kelimesidir. Böyle bir fonksiyon yalnızca başka bir suspend fonksiyonundan veya bir korutinden çağrılabilir. Bir suspend fonksiyonunun içinde, diğer suspend fonksiyonlarını herhangi bir sırayla çağırabilirsiniz ve her çağrı noktası potansiyel bir askıya alma noktasıdır.

Mekanik basittir: bir suspend fonksiyonu başka bir suspend fonksiyonunu çağırdığında, o noktada askıya alınır ve thread'i serbest bırakır. Çağrılan fonksiyon tamamlandıktan sonra, çalışma zamanı kaydedilen konumdan yürütmeye devam eder. Buna işbirlikçi iptal (cooperative cancellation) denir — hiçbir thread bloke edilmez.

  • Askıya Alma — korutin thread'i bloke etmeden serbest bırakır
  • Devam Etme — korutin askıya alındığı yerden devam eder
  • Thread — bir korutin thread A'da askıya alınıp thread B'de devam edebilir
  • İstisnalar — senkron koddaki gibi try/catch ile işlenir

Önemli: bir suspend fonksiyonu varsayılan olarak asenkron değildir. launch veya async kullanılmazsa yürütme sırası sıralı kalır. suspend yalnızca fonksiyonun thread'i bloke etmeden duraklamasına ve korutin bağlamının bir parçası olmasına izin verir. Continuation Passing Style, her suspend fonksiyonunun gizli bir Continuation geri çağrısı aldığı ve derleyicinin askıya almaları ve devam ettirmeleri yönetmek için bir durum makinesi oluşturduğu bir derleme modelidir.

CoroutineScope ve Yapılandırılmış Eşzamanlılık

CoroutineScope, korutinlerin yaşam döngüsünü tanımlayan bir bağlamdır. Tüm korutinler bir kapsam içinde başlatılmalıdır. Bir kapsam iptal edildiğinde (örneğin, bir Activity sona erdiğinde), tüm alt korutinleri otomatik olarak iptal edilir. Bu, arka plan görev sızıntılarını önler. Android Jetpack, her bileşen için hazır kapsamlar sağlar: ViewModel için viewModelScope ve Activity/Fragment için lifecycleScope, ilgili bileşen yok edildiğinde otomatik olarak iptal edilir.

Yapılandırılmış Eşzamanlılık (Structured Concurrency), tüm alt korutinler tamamlanana kadar bir korutinin tamamlanmayacağını garanti eden bir ilkedir. Job hiyerarşisi bir ağaç oluşturur: bir kök korutin bir üst job oluşturur, alt job'lar oluşturur. Bir üst job'ın iptali tüm alt job'lara yayılır. Structured Concurrency, korutinler ve thread'ler arasındaki temel bir farktır.

ScopeNerede Kullanılırİptal
GlobalScopeYalnızca daemon görevleri içinOtomatik iptal edilmez
viewModelScopeAndroid ViewModelViewModel temizlendiğinde
lifecycleScopeAndroid Activity/Fragmentlifecycle yok edildiğinde
coroutineScopesuspend fonksiyonu içindeÜst job iptal edildiğinde

Hata Yönetimi için SupervisorJob

Normal bir Job, bir alt korutin başarısız olduğunda tüm kardeşleri iptal eder. SupervisorJob bir istisnadır: bir alt korutindeki başarısızlık diğerlerini etkilemez. Bu, birden fazla bağımsız görevin paralel olarak yürütüldüğü ve bunlardan birinin diğerlerini iptal etmeye gerek kalmadan çökebileceği durumlarda önemlidir.

Dispatchers ve Korutin Oluşturucular

Dispatchers, korutinlerin hangi thread'lerde yürütüleceğini belirler. Dispatchers.Main — ana Android UI thread'i. Dispatchers.IO — bloke edici işlemler (ağ, disk) için bir havuz. Dispatchers.Default — CPU yoğun görevler için. Dispatchers.Unconfined — geçerli thread'de başlar ancak orada kalacağını garanti etmez. Doğru Dispatcher'ı seçmek performans için kritiktir: Default'ta bir IO görevi hesaplama havuzunu bloke ederken, IO'da bir CPU görevi gereksiz thread'ler oluşturur.

withContext — bir korutin içinde Dispatcher'ı değiştirmek için bir fonksiyondur. Örneğin, JSON ayrıştıran bir suspend fonksiyonu, hesaplama için Dispatchers.Default'a geçebilir ve UI güncellemesi için Dispatchers.Main'e dönebilir. withContext, Android geliştirmede en çok kullanılan oluşturucudur.

Üç Ana Korutin Oluşturucusu

launch — bir korutin başlatır, Job döndürür, sonuç döndürmez (fire-and-forget). async — bir korutin başlatır, await ile sonucu alınabilecek bir Deferred döndürür. runBlocking — bir korutini yürütmek için geçerli thread'i bloke eder (yalnızca testler ve main fonksiyonları için). Oluşturucu seçimi senaryoya bağlıdır: launch olaylar ve güncellemeler için uygundur, async sonuç gerektiren görevler için, runBlocking yalnızca testler veya giriş noktaları için.

Kotlin'de Korutinlerle Kod Örnekleri

Üç pratik senaryoyu inceleyelim: launch ile temel bir korutin, async ile paralel çağrı ve SupervisorJob ile hata yönetimi.

launch ile Korutin Başlatma

viewModelScope.launch, ViewModel bağlamında bir korutin başlatır. ViewModel temizlendiğinde korutin otomatik olarak iptal edilir.

kotlin
class ProfileViewModel : ViewModel() {
    fun loadUser() {
        viewModelScope.launch(Dispatchers.IO) {
            val user = api.fetchUser()
            withContext(Dispatchers.Main) {
                showUser(user)
            }
        }
    }
}

async ile Paralel İstekler

coroutineScope ile async, üç isteği paralel olarak başlatır. Sonuçlar .await() ile toplanır. Herhangi bir istek başarısız olursa tümü iptal edilir.

kotlin
suspend fun loadDashboard(): Dashboard = coroutineScope {
    val user = async { api.fetchUser() }
    val posts = async { api.fetchPosts() }
    val stats = async { api.fetchStats() }
    Dashboard(user.await(), posts.await(), stats.await())
}

SupervisorJob ile Hata Yönetimi

SupervisorJob, her korutinin bağımsız olarak tamamlanmasını sağlar. Bir istekteki hata diğerlerini iptal etmez.

kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
    try { api.fetchUsers() } catch (e: Exception) { log(e) }
}
scope.launch {
    try { api.fetchPosts() } catch (e: Exception) { log(e) }
}

Korutinler vs Thread'ler: Karşılaştırma ve Senaryolar

Thread'ler bir işletim sistemi ilkelidir. Her thread'in kendi yığını (~1 MB) vardır ve oluşturma ve değiştirme için sistem çağrısı gerektirir. Korutinler bir dil ilkelidir, işletim sistemine bağlı değildir. Durumu kaydetmek için Continuation kullanır ve sistem çağrısı olmadan çalışma zamanı seviyesinde geçiş yapar.

  • Bellek — thread ~1 MB, korutin ~100 bayt. 10.000 kat fark
  • Oluşturma — thread ~1 µs syscall, korutin ~0,01 µs (JVM seviyesi)
  • Geçiş — thread ~0,1 µs (syscall), korutin ~0,001 µs (continuation)
  • Maksimum — binlerce thread vs cihaz başına milyonlarca korutin
  • İptal — bir thread harici olarak iptal edilemez (kullanımdan kaldırılan Thread.stop), korutin Job.cancel() ile iptal edilebilir

Google'a (2025) göre, thread'ler yerine korutin kullanmak, Android uygulamalarındaki arka plan görevleri için bellek tüketimini %90-95 oranında azaltır. Tüm modern Android kütüphaneleri (Retrofit, Room, WorkManager), suspend fonksiyonları aracılığıyla yerleşik korutin desteğine sahiptir. Ktor (JetBrains HTTP istemci çerçevesi) da tamamen korutinler üzerine inşa edilmiştir ve geri çağrı API'si olmadan her istek için suspend fonksiyonları sağlar. Room, DAO'daki suspend fonksiyonları aracılığıyla korutinleri destekleyerek ana thread'i bloke etmeden veritabanı sorguları yürütülmesine olanak tanır.

Korutinler Yerine Ne Zaman Thread Kullanılmalı

Thread'ler, JNI aracılığıyla yerel kod, uzun süreli CPU yoğun bloke edici çağrılar (video işleme, simülasyonlar) ve C kütüphaneleriyle entegrasyon için gereklidir. Diğer her şey için — korutinler.

Sıkça Sorulan Sorular

Korutin bir thread'den nasıl farklıdır?

Korutin, mevcut bir thread'de yürütülen askıya alınabilir bir iş birimdir. Thread, kendi yığınına sahip bir sistem kaynağıdır. Korutinler thread'lerden binlerce kat daha hafiftir ve askıya alındığında kaynakları bloke etmez.

Dispatchers.IO nedir ve Default'tan nasıl farklıdır?

Dispatchers.IO, bloke edici G/Ç işlemleri (ağ, dosyalar) için tasarlanmıştır ve gerektiğinde yeni thread'ler oluşturabilir. Dispatchers.Default, CPU yoğun hesaplamalar için sabit boyutlu bir havuza (CPU çekirdeği sayısı) sahiptir.

Çalışan bir korutini nasıl iptal ederim?

Job.cancel() korutini ve tüm alt korutinlerini iptal eder. Bir korutin içinde iptali kontrol etmek için ensureActive() kullanın — korutin iptal edilmişse CancellationException fırlatır.

Korutinler RxJava ile kullanılabilir mi?

Evet — kotlinx-coroutines-rx3 kütüphanesi aracılığıyla. Observable/Single'ı suspend fonksiyonlarına dönüştürmek ve flowable aracılığıyla geri döndürmek için awaitSingle, awaitFirst ve diğer fonksiyonları sağlar.

Korutinlerde Flow nedir?

Flow, soğuk asenkron veri akışıdır ve korutinlerde RxJava Observable'ın eşdeğeridir. Flow değerleri sırayla yayar ve bir istisna veya başarı ile tamamlanır. map, filter, catch ve diğer operatörleri destekler.

Özet

  • Coroutines — Continuation Passing Style ile blokajsız askıya alma özelliğine sahip hafif Kotlin thread'leri
  • suspend — askıya alınabilir fonksiyonları işaretlemek için anahtar kelime
  • Dispatchers thread havuzunu yönetir: Main, IO, Default
  • CoroutineScope korutin yaşam döngüsünü bir bileşene (Activity, ViewModel) bağlar
  • launch sonuçsuz korutin başlatır, async/await — sonuçlu
  • Structured Concurrency alt korutinlerin hiyerarşik iptalini garanti eder
  • Korutinler vs thread'ler — korutinler 10.000 kat daha hafif ve Android standardı

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun