suspend function: nedir, sözdizimi ve koroutinlerde çalışması

Yazar: IT Sectr Yayınlanma: 2026-06-22 Okuma süresi: 9 dk

Suspend function bir iş parçacığını bloke etmeden yürütmesini duraklatabilen ve daha sonra aynı koroutinde devam edebilen suspend değiştiricisine sahip bir işlevdir. JetBrains Kotlin Docs, 2025'e göre, suspend işlevleri geri aramalar olmadan eşzamansızlık sağlayan koroutinlerin temel yapı taşıdır. Her suspend işlevi, askıya alma noktalarının verimli yönetimine izin veren Continuation tabanlı bir durum makinesine derlenir.

Önemli noktalar

  • Suspend — bir işlevi duraklatılabilir (eşzamansız) olarak işaretleyen Kotlin anahtar sözcüğü
  • Continuation — derleyicinin durumu kaydetmek için her suspend işlevine eklediği gizli parametre
  • Askıya alma noktaları — diğer suspend işlevlerinin çağrıldığı, bir koroutinin bloke etmeden durabileceği yerler
  • Durum makinesi — her askıya alma noktasının ayrı bir durum olduğu, suspend işlevinin iç temsili
  • Yalnızca koroutinden çağrı — suspend işlevleri yalnızca başka bir suspend işlevinden veya launch/async'den çağrılabilir

Kotlin'de suspend function nedir?

Suspend function, iş parçacığını bloke etmeden bir veya daha fazla noktada yürütmeyi duraklatabilen suspend anahtar sözcüğüyle bildirilmiş bir işlevdir. Başka bir suspend işlevi içindeki her suspend işlevi çağrısı, potansiyel bir askıya alma noktasıdır.

kotlin
suspend fun fetchUserData(): User {
    val response = httpClient.get("/user")
    return parser.parse(response)
}

Kotlin derleyicisi böyle bir işlevi durum makinesine dönüştürür. Her askıya alma noktası (başka bir suspend işlevine çağrı) bir durum (label) haline gelir. Geçerli iş parçacığı durumlar arasında serbest bırakılır ve beklenen işlem tamamlandıktan sonra yürütme bir sonraki durumdan devam eder.

Tarihçe

Suspend işlevleri, deneysel bir özellik olarak Kotlin 1.3'te (2018) koroutinlerle birlikte ortaya çıktı ve Kotlin 1.5'te (2021) kararlı hale geldi. Bundan önce, Kotlin/Java'da eşzamansızlık geri aramalar, RxJava ve CompletableFuture aracılığıyla sağlanıyordu. Suspend işlevleri, doğrusal sözdizimi ve otomatik iş parçacığı yönetimi ile bir alternatif sundu.

Suspend işlevleri nasıl çalışır: Continuation ve durum makinesi

Suspend işlevlerinin iç işleyişini anlamak, koroutinlerle doğru çalışmanın anahtarıdır. Normal işlevlerin aksine, her suspend işlevi Continuation arabirimine sahip bir sınıfa derlenir.

Continuation — gizli parametre

Kotlin derleyicisi, her suspend işlevinin parametre listesinin sonuna Continuation türünde bir parametre ekler. Continuation şunları içerir:

  • context — CoroutineContext (dağıtıcı, iş, bağlam öğeleri)
  • resumeWith — bir sonuç veya istisna ile yürütmeyi devam ettirme yöntemi
  • label — durum makinesindeki geçerli durumun dizini

Durum makinesi örneği

Diyelim ki diğer suspend işlevlerine iki çağrı yapan bir suspend işlevimiz var:

kotlin
suspend fun process() {
    val a = stepOne()
    val b = stepTwo(a)
    println(b)
}

Derleyici bunu etiketli bir durum makinesine dönüştürür:

kotlin
// Simplified generated code representation
fun process(cont: Continuation<Unit>): Any? {
    val cont = cont as ProcessContinuation
    when (cont.label) {
        0 -> {
            cont.label = 1
            if (stepOne(cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
        }
        1 -> {
            cont.label = 2
            val a = cont.result as TypeA
            if (stepTwo(a, cont) == COROUTINE_SUSPENDED) return COROUTINE_SUSPENDED
        }
        2 -> {
            println(cont.result)
            Unit
        }
    }
}

Önemli gözlem: işlev COROUTINE_SUSPENDED döndürürse, geçerli iş parçacığı serbest bırakılır. Eşzamansız işlem tamamlandığında, Continuation.resumeWith çağrılır ve durum makinesi bir sonraki etiketten devam eder.

Suspend işlev sözdizimi: bildirim ve çağrı

Bir suspend işlevi bildirmek, fun'dan önceki suspend anahtar sözcüğü dışında normal bir işlevden farklı değildir. Tek bir kısıtlama vardır: bir suspend işlevi yalnızca bir koroutinden veya başka bir suspend işlevinden çağrılabilir.

Temel bildirim

kotlin
suspend fun delayAndReturn(ms: Long): String {
    delay(ms)
    return "Done after ${ms}ms"
}

Bu örnekte, delay de bir suspend işlevidir ve iş parçacığını bloke etmeden koroutini belirtilen milisaniye kadar duraklatır. Gecikmeden sonra yürütme devam eder.

Koroutinden çağrı

kotlin
fun main() = runBlocking {
    val result = delayAndReturn(1000)
    println(result)
}

runBlocking, normal dünya ile koroutinler arasında bir köprü oluşturur. Lambda içinde herhangi bir suspend işlevi çağrılabilir.

Suspend lambdalar ve işlevsel türler

Kotlin, işlevsel türlerin suspend sürümlerini destekler — suspend () -> T ve suspend (A) -> B. Bu, eşzamansız lambdaların yüksek dereceli işlevlere iletilmesine olanak tanır:

kotlin
suspend fun  withRetry(
    retries: Int = 3,
    block: suspend () -> T
): T {
    repeat(retries - 1) {
        try { return block() }
        catch (_: Exception) { delay(100) }
    }
    return block()
}

withRetry işlevi bir suspend lambda alır ve hata durumunda yürütmesini yeniden dener. Bu, yeniden denemeli ağ istekleri için tipik bir kalıptır.

Suspend işlevlerinin normal işlevlerden farkları

Suspend ve normal işlevler arasındaki farklar, yalnızca bir değiştirici eklemenin ötesine geçer. Temel farklılıklara bakalım.

ÖzellikNormal işlevSuspend işlev
Yürütme iş parçacığıTamamlanana kadar iş parçacığını bloke ederİş parçacığını serbest bırakıp sonra devam edebilir
Derleyici parametreleriYalnızca belirtilen parametrelerSonda örtük Continuation
Normal işlevden çağrıEvetHayır
YığınFiziksel iş parçacığı yığınıYığında durum makinesi + noktalar arasında fiziksel yığın
Dönüş değeriDoğrudan değerDeğer veya COROUTINE_SUSPENDED
PerformansMinimum ek yük~durum makinesi başına birkaç nanosaniye (Kotlin 1.9+)

Suspend işlevleri neden normal işlevlerden çağrılamaz

Normal bir işlevde Continuation yoktur — durumu kaydedecek yeri ve yürütmeyi devam ettirecek bir şeyi yoktur. Normal bir işlevden bir suspend işlevi çağırmanız gerekiyorsa, runBlocking (testler için) veya CoroutineScope.launch (yaşam döngüsü bilinciyle üretim için) kullanın.

Android'de suspend işlev örnekleri

Kotlin ile Android uygulamalarında suspend işlevlerini kullanmanın üç gerçek senaryosuna bakalım.

Örnek 1: Suspend sorgularıyla Room DAO

Room, suspend işlevlerini doğrudan destekler — sorgu otomatik olarak bir arka plan iş parçacığında yürütülür:

kotlin
@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE id = :id")
    suspend fun getUser(id: Int): User?

    @Insert
    suspend fun insertUser(user: User)
}

Room, sorguyu yürütmek için dahili olarak Dispatchers.IO kullanır ve sonuç, suspend işlevinin çağrıldığı dağıtıcıda döndürülür.

Örnek 2: Ekran yüklemesi için suspend işlevlerinin birleştirilmesi

kotlin
class ProfileViewModel : ViewModel() {
    private val repo = ProfileRepository()

    fun loadProfile(id: String) {
        viewModelScope.launch {
            val profile = repo.getProfile(id)
            _profile.value = profile
        }
    }
}

ViewModelScope.launch bir koroutin oluşturur ve içinde getProfile suspend işlevi çağrılır. Sonuç alındıktan sonra kullanıcı arayüzü ana iş parçacığında güncellenir.

Örnek 3: Sıralı eşzamansız adımlar

kotlin
suspend fun placeOrder(cart: Cart): OrderResult {
    val validated = validateCart(cart)
    val payment = processPayment(validated)
    val receipt = sendReceipt(payment)
    return receipt
}

Üç suspend işlevi sırayla yürütülür. Her adımda, koroutin iş parçacığını bloke etmeden duraklayabilir. Herhangi bir adım bir istisna atarsa, kalan adımlar yürütülmez ve bu da hatalı sipariş durumlarına karşı korur.

Suspend işlevleriyle çalışırken yaygın hatalar

Deneyimli Kotlin geliştiricileri bile suspend işlevleri tasarlarken hatalar yapar. En yaygın olanlarına bakalım.

Hata 1: Suspend içinde bloke edici çağrılar

Bir suspend işlevi, kodu otomatik olarak eşzamansız yapmaz. Thread.sleep(), InputStream.read() ve diğer bloke edici çağrılar yine de iş parçacığını bloke eder. Bloke edici işlemleri sarmak için withContext(Dispatchers.IO) kullanın.

Hata 2: Gereksiz yere suspend işlevleri oluşturmak

Bir işlev başka suspend işlevlerini çağırmıyorsa ve eşzamansız işlemler gerçekleştirmiyorsa — suspend değiştiricisi gereksizdir. Durum makinesine ek yük ekler ve çağrı bağlamını kısıtlar. Bir işlevi yalnızca gerçekten durakladığında suspend yapın.

Hata 3: CancellationException'ı yok saymak

Bir koroutin iptal edildiğinde, suspend işlevleri CancellationException fırlatır. Bunu düşünmeden yakalamayın — çağıran kodu iptali doğru şekilde tamamlama yeteneğinden mahrum bırakırsınız. Sonlandırma işlemi yapmanız gerekiyorsa, bir finally bloğu ve NonCancellable kullanın.

kotlin
suspend fun safeOperation() {
    try {
        doWork()
    } finally {
        withContext(NonCancellable) {
            cleanup()
        }
    }
}

finally bloğu her zaman yürütülür, iptalde dahil, ve NonCancellable temizliğin kesintiye uğramamasını sağlar.

Hata 4: Geri aramalardan suspend işlevleri çağırmak

Bir koroutin oluşturmadan doğrudan bir geri aramadan suspend işlevi çağıramazsınız. Geri arama stilini koroutinlere uyarlamak için suspendCoroutine veya suspendCancellableCoroutine kullanın.

Sıkça sorulan sorular

Bir suspend işlevi askıya alma noktası içermeyebilir mi?

Evet, teknik olarak bir suspend işlevi diğer suspend işlevlerini çağırmayabilir. Derleyici, tek bir durumla (label 0) bir durum makinesi oluşturacaktır. Ancak, böyle bir işlevin pratik bir faydası yoktur — normal bir işlev gibi çalışır ancak ek yük ile. Gereksiz yere suspend kullanmayın.

Suspend işlevleri nasıl hata ayıklanır?

Kotlin, kotlinx-coroutines-debug sağlar — DebugProbes ve koroutin izleme araçları içeren bir kitaplık. Arctic Fox'tan itibaren Android Studio'da, Hata Ayıklayıcı'da etkin koroutinleri, durumlarını ve askıya alma noktalarını gösteren yerleşik bir Coroutines sekmesi bulunur.

Askıya alma noktalarının sayısı performansı etkiler mi?

Her askıya alma noktası durum makinesinde yeni bir durum oluşturur. Çoğu uygulama için bir noktanın ek yükü birkaç nanosaniyedir (Kotlin 1.9+). Yalnızca bir döngüde on binlerce nokta olduğunda işlemleri birleştirmeyi veya sequence/flow kullanmayı düşünmelisiniz.

Bir suspend işlevi diğer dillerdeki async/await'ten nasıl farklıdır?

Kotlin'de, suspend bir işlev türü değiştiricisidir, bir dönüş değeri işaretçisi değil (C#'taki async gibi). Herhangi bir suspend işlevi herhangi bir parametreye ve dönüş türüne sahip olabilir ve çağrısı sözdizimsel olarak normal bir işlev çağrısından farklı değildir — çağrı noktasında await operatörü yoktur.

Bir geri arama işlevi saspend'e nasıl dönüştürülür?

Uyarlama için suspendCancellableCoroutine kullanın. İçinde, continuation.resume() çağıran bir geri arama kaydedersiniz ve geri arama abonelik iptalini destekliyorsa bir iptal belirteci döndürürsünüz. Bu, eski Android API'lerini sarmak için standart kalıptır.

Özet

  • Suspend function — Continuation mekanizması aracılığıyla bir iş parçacığını bloke etmeden yürütmeyi duraklatabilen suspend değiştiricili işlev
  • Durum makinesi — Kotlin bayt kodunda bir suspend işlevinin iç temsili, her askıya alma noktası bir etiketle ayrı bir durum
  • Continuation — koroutin bağlamını ve yürütmeyi devam ettirmek için resumeWith yöntemini içeren gizli parametre
  • Yalnızca koroutinden çağrı — suspend işlevlerine runBlocking veya CoroutineScope olmadan normal işlevlerden erişilemez
  • Bloke edici işlemler suspend içinde withContext(Dispatchers.IO) gerektirir — aksi halde iş parçacığı bloke olur
  • Room ve Retrofit suspend işlevlerini yerel olarak destekler, arka plan iş parçacıklarını otomatik olarak yönetir
  • CancellationException — iptali finally + NonCancellable ile yönetin, CancellationException'ı düşünmeden yakalamayın

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