suspend function: Was es ist, Syntax und Funktionsweise in Koroutinen

Autor: IT Sectr Veröffentlicht: 2026-06-22 Lesezeit: 9 Min.

Suspend function ist eine Funktion mit dem suspend-Modifikator, die ihre Ausführung anhalten kann, ohne einen Thread zu blockieren, und später in derselben Koroutine fortsetzen kann. Laut JetBrains Kotlin Docs, 2025 sind Suspend-Funktionen ein grundlegender Baustein von Koroutinen und bieten Asynchronität ohne Callbacks. Jede Suspend-Funktion wird in eine auf Continuation basierende Zustandsmaschine kompiliert, die eine effiziente Verwaltung von Aussetzungspunkten ermöglicht.

Wichtige Punkte

  • Suspend — ein Kotlin-Schlüsselwort, das eine Funktion als anhaltbar (asynchron) markiert
  • Continuation — ein versteckter Parameter, den der Compiler jeder Suspend-Funktion hinzufügt, um den Zustand zu speichern
  • Aussetzungspunkte — Stellen, an denen andere Suspend-Funktionen aufgerufen werden, wo eine Koroutine ohne Blockieren anhalten kann
  • Zustandsmaschine — die interne Darstellung einer Suspend-Funktion, bei der jeder Aussetzungspunkt ein separater Zustand ist
  • Aufruf nur aus Koroutine — Suspend-Funktionen können nur aus einer anderen Suspend-Funktion oder aus launch/async aufgerufen werden

Was ist eine suspend function in Kotlin?

Suspend function ist eine mit dem suspend-Schlüsselwort deklarierte Funktion, die die Ausführung an einem oder mehreren Punkten anhalten kann, ohne den Thread zu blockieren. Jeder Aufruf einer Suspend-Funktion innerhalb einer anderen Suspend-Funktion ist ein potenzieller Aussetzungspunkt.

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

Der Kotlin-Compiler übersetzt eine solche Funktion in eine Zustandsmaschine. Jeder Aussetzungspunkt (ein Aufruf einer anderen Suspend-Funktion) wird zu einem Zustand (Label). Der aktuelle Thread wird zwischen den Zuständen freigegeben, und nach Abschluss der erwarteten Operation wird die Ausführung vom nächsten Zustand aus fortgesetzt.

Geschichte

Suspend-Funktionen erschienen in Kotlin 1.3 (2018) zusammen mit Koroutinen als experimentelles Feature und wurden in Kotlin 1.5 (2021) stabil. Davor wurde Asynchronität in Kotlin/Java durch Callbacks, RxJava und CompletableFuture erreicht. Suspend-Funktionen boten eine Alternative mit linearer Syntax und automatischer Thread-Verwaltung.

Wie Suspend-Funktionen arbeiten: Continuation und Zustandsmaschine

Das Verständnis der inneren Arbeitsweise von Suspend-Funktionen ist der Schlüssel zur korrekten Arbeit mit Koroutinen. Im Gegensatz zu regulären Funktionen wird jede Suspend-Funktion in eine Klasse mit dem Continuation-Interface kompiliert.

Continuation — der versteckte Parameter

Der Kotlin-Compiler fügt am Ende jeder Parameterliste einer Suspend-Funktion einen Parameter vom Typ Continuation hinzu. Continuation enthält:

  • context — CoroutineContext (Dispatcher, Job, Kontextelemente)
  • resumeWith — Methode zum Fortsetzen der Ausführung mit einem Ergebnis oder einer Ausnahme
  • label — Index des aktuellen Zustands in der Zustandsmaschine

Beispiel einer Zustandsmaschine

Angenommen, wir haben eine Suspend-Funktion mit zwei Aufrufen anderer Suspend-Funktionen:

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

Der Compiler wandelt sie in eine Zustandsmaschine mit Labels um:

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
        }
    }
}

Wichtige Beobachtung: Wenn die Funktion COROUTINE_SUSPENDED zurückgibt, wird der aktuelle Thread freigegeben. Wenn die asynchrone Operation abgeschlossen ist, wird Continuation.resumeWith aufgerufen, und die Zustandsmaschine fährt mit dem nächsten Label fort.

Syntax von Suspend-Funktionen: Deklaration und Aufruf

Die Deklaration einer Suspend-Funktion unterscheidet sich nicht von einer regulären Funktion, außer durch das Schlüsselwort suspend vor fun. Es gibt nur eine Einschränkung: Eine Suspend-Funktion kann nur von einer Koroutine oder einer anderen Suspend-Funktion aufgerufen werden.

Basissyntax

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

In diesem Beispiel ist delay ebenfalls eine Suspend-Funktion, die die Koroutine für die angegebene Anzahl von Millisekunden anhält, ohne den Thread zu blockieren. Nach der Verzögerung wird die Ausführung fortgesetzt.

Aufruf aus einer Koroutine

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

runBlocking erstellt eine Brücke zwischen der normalen Welt und Koroutinen. Innerhalb des Lambdas können beliebige Suspend-Funktionen aufgerufen werden.

Suspend-Lambdas und funktionale Typen

Kotlin unterstützt Suspend-Versionen funktionaler Typen — suspend () -> T und suspend (A) -> B. Dies ermöglicht die Übergabe asynchroner Lambdas an Funktionen höherer Ordnung:

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

Die Funktion withRetry nimmt ein Suspend-Lambda entgegen und wiederholt dessen Ausführung bei Fehlern. Dies ist ein typisches Muster für Netzwerkanfragen mit Wiederholungsversuchen.

Wie sich Suspend-Funktionen von regulären unterscheiden

Die Unterschiede zwischen Suspend- und regulären Funktionen gehen über das bloße Hinzufügen eines Modifikators hinaus. Betrachten wir die wesentlichen Unterschiede.

EigenschaftReguläre FunktionSuspend-Funktion
Ausführungs-ThreadBlockiert den Thread bis zur FertigstellungKann Thread freigeben und später fortsetzen
Compiler-ParameterNur angegebene ParameterImplizites Continuation am Ende
Aufruf aus regulärer FunktionJaNein
StackPhysischer Thread-StackZustandsmaschine im Heap + physischer Stack zwischen Punkten
RückgabewertDirekter WertWert oder COROUTINE_SUSPENDED
LeistungMinimaler Overhead~einige Nanosekunden pro Zustandsmaschine (Kotlin 1.9+)

Warum Suspend-Funktionen nicht von regulären aufgerufen werden können

Eine reguläre Funktion hat kein Continuation — sie hat keinen Ort, um den Zustand zu speichern, und nichts, um die Ausführung fortzusetzen. Wenn Sie eine Suspend-Funktion von einer regulären Funktion aus aufrufen müssen, verwenden Sie runBlocking (für Tests) oder CoroutineScope.launch (für die Produktion mit Lebenszyklus-Bewusstsein).

Beispiele für Suspend-Funktionen in Android

Betrachten wir drei reale Szenarien für die Verwendung von Suspend-Funktionen in Android-Apps mit Kotlin.

Beispiel 1: Room DAO mit Suspend-Abfragen

Room unterstützt Suspend-Funktionen direkt — die Abfrage wird automatisch im Hintergrundthread ausgeführt:

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

    @Insert
    suspend fun insertUser(user: User)
}

Room verwendet intern Dispatchers.IO zur Ausführung der Abfrage, und das Ergebnis wird auf dem Dispatcher zurückgegeben, auf dem die Suspend-Funktion aufgerufen wurde.

Beispiel 2: Zusammensetzung von Suspend-Funktionen zum Bildschirmladen

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

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

ViewModelScope.launch erstellt eine Koroutine, in der die Suspend-Funktion getProfile aufgerufen wird. Nach Erhalt des Ergebnisses wird die UI im Hauptthread aktualisiert.

Beispiel 3: Sequenzielle asynchrone Schritte

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

Drei Suspend-Funktionen werden nacheinander ausgeführt. Bei jedem Schritt kann die Koroutine anhalten, ohne den Thread zu blockieren. Wenn ein Schritt eine Ausnahme auslöst, werden die übrigen Schritte nicht ausgeführt, was vor falschen Bestellungszuständen schützt.

Häufige Fehler bei der Arbeit mit Suspend-Funktionen

Selbst erfahrene Kotlin-Entwickler machen Fehler beim Entwurf von Suspend-Funktionen. Betrachten wir die häufigsten.

Fehler 1: Blockierende Aufrufe innerhalb von suspend

Eine Suspend-Funktion macht Code nicht automatisch asynchron. Thread.sleep(), InputStream.read() und andere blockierende Aufrufe blockieren weiterhin den Thread. Verwenden Sie withContext(Dispatchers.IO), um blockierende Operationen zu kapseln.

Fehler 2: Erstellen von Suspend-Funktionen ohne Notwendigkeit

Wenn eine Funktion keine anderen Suspend-Funktionen aufruft und keine asynchronen Operationen ausführt — ist der suspend-Modifikator überflüssig. Er fügt Overhead für die Zustandsmaschine hinzu und schränkt den Aufrufkontext ein. Machen Sie eine Funktion nur dann zu suspend, wenn sie tatsächlich anhält.

Fehler 3: Ignorieren von CancellationException

Wenn eine Koroutine abgebrochen wird, werfen Suspend-Funktionen CancellationException. Fangen Sie sie nicht gedankenlos ab — Sie berauben den aufrufenden Code der Fähigkeit, den Abbruch korrekt abzuschließen. Wenn Sie eine Abschlussoperation durchführen müssen, verwenden Sie einen finally-Block und NonCancellable.

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

Der finally-Block wird immer ausgeführt, auch bei Abbruch, und NonCancellable stellt sicher, dass die Bereinigung nicht unterbrochen wird.

Fehler 4: Aufrufen von Suspend-Funktionen aus Callbacks

Sie können eine Suspend-Funktion nicht direkt aus einem Callback aufrufen, ohne eine Koroutine zu erstellen. Verwenden Sie suspendCoroutine oder suspendCancellableCoroutine, um den Callback-Stil an Koroutinen anzupassen.

Häufig gestellte Fragen

Kann eine Suspend-Funktion keine Aussetzungspunkte enthalten?

Ja, technisch gesehen kann eine Suspend-Funktion keine anderen Suspend-Funktionen aufrufen. Der Compiler erstellt eine Zustandsmaschine mit einem einzigen Zustand (Label 0). Allerdings hat eine solche Funktion keinen praktischen Nutzen — sie wird wie eine reguläre ausgeführt, jedoch mit Overhead. Verwenden Sie suspend nicht unnötig.

Wie debuggt man Suspend-Funktionen?

Kotlin bietet kotlinx-coroutines-debug — eine Bibliothek mit DebugProbes und Koroutinen-Tracing-Werkzeugen. In Android Studio ab Arctic Fox gibt es einen integrierten Coroutines-Tab im Debugger, der aktive Koroutinen, ihren Zustand und Aussetzungspunkte anzeigt.

Beeinflusst die Anzahl der Aussetzungspunkte die Leistung?

Jeder Aussetzungspunkt erzeugt einen neuen Zustand in der Zustandsmaschine. Für die meisten Anwendungen beträgt der Overhead eines Punktes wenige Nanosekunden (Kotlin 1.9+). Nur bei Zehntausenden von Punkten in einer Schleife sollten Sie in Betracht ziehen, Operationen zu kombinieren oder sequence/flow zu verwenden.

Wie unterscheidet sich eine Suspend-Funktion von async/await in anderen Sprachen?

In Kotlin ist suspend ein Funktionsmodifikator, kein Rückgabewert-Marker (wie async in C#). Jede Suspend-Funktion kann beliebige Parameter und Rückgabetypen haben, und ihr Aufruf unterscheidet sich syntaktisch nicht von einem regulären Funktionsaufruf — es gibt keinen await-Operator an der Aufrufstelle.

Wie konvertiert man eine Callback-Funktion in suspend?

Verwenden Sie suspendCancellableCoroutine zur Anpassung. Darin registrieren Sie einen Callback, der continuation.resume() aufruft, und geben einen Abbruchtoken zurück, wenn der Callback das Abbestellen unterstützt. Dies ist das Standardmuster zum Umwickeln alter Android-APIs.

Zusammenfassung

  • Suspend function — Funktion mit dem suspend-Modifikator, die die Ausführung ohne Thread-Blockierung über den Continuation-Mechanismus anhalten kann
  • Zustandsmaschine — interne Darstellung einer Suspend-Funktion im Kotlin-Bytecode, bei der jeder Aussetzungspunkt ein separater Zustand mit einem Label ist
  • Continuation — ein versteckter Parameter, der den Koroutinenkontext und die resumeWith-Methode zum Fortsetzen der Ausführung enthält
  • Aufruf nur aus Koroutine — Suspend-Funktionen sind von regulären Funktionen ohne runBlocking oder CoroutineScope nicht zugänglich
  • Blockierende Operationen innerhalb von suspend erfordern withContext(Dispatchers.IO) — sonst blockiert der Thread
  • Room und Retrofit unterstützen Suspend-Funktionen nativ und verwalten automatisch Hintergrundthreads
  • CancellationException — behandeln Sie Abbruch über finally + NonCancellable, fangen Sie CancellationException nicht gedankenlos ab

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch