---
title: "Suspend em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/suspend/"
markdown_url: "https://kotlin.dev.br/glossario/suspend.MD"
description: "Aprenda o que é a palavra-chave suspend em Kotlin, como criar funções suspensas e sua relação com coroutines."
date: "2026-02-05"
author: "Karina Melo"
---

# Suspend em Kotlin: O que É e Como Funciona | Kotlin Brasil

Aprenda o que é a palavra-chave suspend em Kotlin, como criar funções suspensas e sua relação com coroutines.


## O que é `suspend` em Kotlin?

A palavra-chave `suspend` marca uma função que pode ser **pausada e retomada** sem bloquear a thread em que está rodando. É o coração do sistema de coroutines do Kotlin.

Uma função `suspend` só pode ser chamada dentro de outra função `suspend` ou dentro de uma coroutine. O compilador garante isso em tempo de compilação, então não tem como errar.

### Sintaxe básica

```kotlin
import kotlinx.coroutines.*

suspend fun buscarUsuario(id: Int): String {
    delay(1000) // Simula uma operacao demorada
    return "Usuário #$id"
}

fun main() = runBlocking {
    val usuario = buscarUsuario(42)
    println(usuario) // Usuário #42
}
```

A função `buscarUsuario` é suspensa — ela pode pausar no `delay` e liberar a thread para fazer outras coisas. Quando o tempo passa, ela retoma de onde parou.

### O que acontece por baixo dos panos?

Quando o compilador encontra uma função `suspend`, ele transforma ela numa máquina de estados usando **continuations**. Na prática, a função é dividida em pedaços que podem ser executados em momentos diferentes.

Você não precisa se preocupar com esses detalhes pra usar, mas é bom saber que não tem mágica — é tudo gerado em tempo de compilação.

### Combinando funções suspend

```kotlin
import kotlinx.coroutines.*

suspend fun buscarNome(): String {
    delay(500)
    return "Fernanda"
}

suspend fun buscarCidade(): String {
    delay(500)
    return "Recife"
}

fun main() = runBlocking {
    val inicio = System.currentTimeMillis()

    val nome = buscarNome()
    val cidade = buscarCidade()

    val tempo = System.currentTimeMillis() - inicio
    println("$nome mora em $cidade (${tempo}ms)")
    // Fernanda mora em Recife (~1000ms - sequencial)
}
```

No exemplo acima, as chamadas são sequenciais. Se quiser executar em paralelo, use `async` — aí o tempo cai pela metade.

### Execução paralela com async

Quando duas funções `suspend` são independentes entre si, você pode executá-las em paralelo usando `async` e `await`. Isso reduz o tempo total de execução significativamente.

```kotlin
import kotlinx.coroutines.*

suspend fun buscarPedidos(userId: Int): List<String> {
    delay(800)
    return listOf("Pedido #101", "Pedido #102")
}

suspend fun buscarNotificacoes(userId: Int): List<String> {
    delay(600)
    return listOf("Novo comentário", "Promoção disponível")
}

fun main() = runBlocking {
    val inicio = System.currentTimeMillis()

    val pedidos = async { buscarPedidos(1) }
    val notificacoes = async { buscarNotificacoes(1) }

    println("Pedidos: ${pedidos.await()}")
    println("Notificações: ${notificacoes.await()}")

    val tempo = System.currentTimeMillis() - inicio
    println("Tempo total: ${tempo}ms") // ~800ms em vez de ~1400ms
}
```

Nesse exemplo, ambas as chamadas iniciam ao mesmo tempo. O tempo total é determinado pela operação mais lenta, não pela soma das duas.

### Funções suspend com tratamento de erros

Funções `suspend` funcionam perfeitamente com `try-catch`, o que torna o tratamento de erros muito mais natural do que callbacks aninhados.

```kotlin
import kotlinx.coroutines.*
import java.io.IOException

suspend fun buscarDadosDoServidor(): String {
    delay(500)
    // Simulando uma falha de rede
    throw IOException("Falha na conexão")
}

fun main() = runBlocking {
    try {
        val dados = buscarDadosDoServidor()
        println(dados)
    } catch (e: IOException) {
        println("Erro ao buscar dados: ${e.message}")
        // Erro ao buscar dados: Falha na conexão
    }
}
```

### Regras importantes

- Funções `suspend` só podem ser chamadas de coroutines ou de outras funções `suspend`.
- `suspend` não torna a função assíncrona por si só — ela apenas **permite** a suspensão.
- Funções normais não podem chamar funções `suspend` diretamente.

### Casos de Uso no Mundo Real

- **Chamadas de API REST**: Funções `suspend` são ideais para requisições HTTP. Bibliotecas como Ktor Client e Retrofit com suporte a coroutines expõem suas operações como funções `suspend`, permitindo fazer chamadas de rede sem bloquear a thread principal.
- **Acesso a banco de dados**: O Room (Android) e o Exposed (backend) permitem definir queries como funções `suspend`. Isso garante que consultas pesadas não travem a interface do usuário nem bloqueiem threads do servidor.
- **Leitura e escrita de arquivos**: Operações de I/O demoradas podem ser encapsuladas em funções `suspend` usando `withContext(Dispatchers.IO)`, mantendo a thread principal livre para outras tarefas.
- **Processamento em lote**: Quando você precisa processar milhares de itens (enviar emails, gerar relatórios), funções `suspend` combinadas com `Flow` permitem processar item a item sem consumir memória excessiva.

### Boas Práticas

- **Use `withContext` para trocar de dispatcher**: Quando uma função `suspend` precisa fazer I/O ou computação pesada, envolva o trecho com `withContext(Dispatchers.IO)` ou `withContext(Dispatchers.Default)` para não bloquear o dispatcher atual.
- **Mantenha funções suspend seguras para a main thread**: Uma função `suspend` bem escrita pode ser chamada de qualquer dispatcher sem risco. Ela mesma deve cuidar de trocar para o dispatcher adequado internamente.
- **Prefira structured concurrency**: Use `coroutineScope` dentro de funções `suspend` quando precisar lançar coroutines filhas. Isso garante que todas terminem antes da função retornar.
- **Não marque como `suspend` sem necessidade**: Só adicione `suspend` quando a função realmente precisa chamar outra função suspensa. Marcar funções desnecessariamente como `suspend` força quem chama a usar coroutines sem motivo.
- **Documente o dispatcher esperado**: Se a função precisa ser chamada de um dispatcher específico, deixe isso claro na documentação com `@Throws` ou comentários.

### Erros Comuns

- **Chamar função suspend fora de uma coroutine**: O erro mais frequente de quem começa. Funções `suspend` precisam ser chamadas dentro de `runBlocking`, `launch`, `async` ou outra função `suspend`. O compilador vai reclamar se você tentar chamar de uma função normal.
- **Usar `runBlocking` em produção**: `runBlocking` bloqueia a thread atual, anulando a vantagem das coroutines. Use apenas em `main()` ou em testes. Em código de produção, prefira `launch` ou `async`.
- **Esquecer de trocar o dispatcher para I/O**: Chamar operações de I/O bloqueantes (como leitura de arquivo com `java.io.File`) dentro de uma função `suspend` sem usar `withContext(Dispatchers.IO)` pode travar o dispatcher principal.
- **Ignorar o cancelamento**: Funções `suspend` devem respeitar o cancelamento da coroutine. Se você faz loops longos, verifique `isActive` ou use `ensureActive()` para que o cancelamento funcione corretamente.
- **Misturar callbacks com suspend**: Evite usar callbacks dentro de funções `suspend`. Se precisa integrar com APIs baseadas em callback, use `suspendCancellableCoroutine` para convertê-las corretamente.

### Perguntas Frequentes

**Qual a diferença entre `suspend` e `async`?** `suspend` é um modificador de função que indica que ela pode ser pausada. `async` é um builder de coroutine que executa uma função `suspend` e retorna um `Deferred` com o resultado. São conceitos complementares: `suspend` define a capacidade de pausar, e `async` é uma das formas de executar funções suspensas.

**Posso chamar uma função `suspend` de Java?** Não diretamente. O compilador Kotlin transforma funções `suspend` adicionando um parâmetro `Continuation` extra. Para chamá-las de Java, você precisa trabalhar com a API de `Continuation` manualmente ou usar wrappers que convertem para `CompletableFuture`.

**Funções `suspend` rodam em outra thread automaticamente?** Não. Uma função `suspend` roda no dispatcher da coroutine que a chamou. Se precisa rodar em outra thread, use `withContext` para especificar o dispatcher desejado. A suspensão em si não implica troca de thread.

**Quantas funções `suspend` posso ter rodando ao mesmo tempo?** Não há limite prático imposto pela linguagem. Coroutines são muito leves (ocupam poucos bytes de memória), então é possível ter milhares ou até milhões de coroutines simultâneas, ao contrário de threads que consomem muito mais recursos.

### Termos Relacionados

- [Coroutines](/glossario/coroutines) — O mecanismo de concorrência do Kotlin que utiliza funções `suspend`.
- [Flow](/glossario/flow) — Streams assíncronos construídos sobre funções `suspend`.
- [val](/glossario/val) — Declaração de variáveis somente leitura, frequentemente usada para armazenar resultados de funções `suspend`.
- [fun](/glossario/fun) — A palavra-chave para declarar funções em Kotlin, combinada com `suspend` para criar funções suspensas.

`suspend` é a base de tudo que envolve concorrência em Kotlin. Dominar esse conceito abre as portas para coroutines, Flow e muito mais.
