Módulo 9 - Async e asyncio

O problema do I/O que espera

9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

Velocidade

O que você vai aprender

  • Enxergar a espera de I/O como tempo desperdiçado.
  • Entender a ideia de aproveitar a espera para outra tarefa.
  • Comparar a abordagem de async com a de threads.
  • Reconhecer quando o async faz sentido.

Onde o tempo se perde

Imagine um programa que busca dados de dez serviços na internet, um a um. Cada chamada leva, digamos, meio segundo, quase todo esse tempo apenas esperando o servidor responder. Feitas em sequência, as dez chamadas somam cinco segundos, mas durante quase todo esse período o seu processador não fez nada: ficou parado, esperando pacotes chegarem pela rede. Esse é o desperdício central do I/O. O trabalho de verdade, montar o pedido e ler a resposta, leva milissegundos; o resto é espera pura. Aproveitar essa ociosidade para adiantar outras chamadas é o que transforma cinco segundos em pouco mais de meio.

No módulo anterior você resolveu esse mesmo problema com threads, e funciona bem. O async ataca o desperdício por outro caminho. Em vez de várias threads que o sistema alterna à força, existe um único thread e um coordenador esperto, o event loop. Cada tarefa avança até topar com uma espera e, nesse ponto, avisa educadamente que vai aguardar e devolve o controle ao loop, que aproveita para tocar outra tarefa que já esteja pronta. Quando a resposta da primeira chega, o loop volta a ela. Tudo isso sem sair de um único thread.

Cooperativo contra preemptivo

A diferença de fundo entre threads e async é quem decide a hora de trocar de tarefa. Com threads, a troca é preemptiva: o sistema pode interromper uma thread a qualquer momento, mesmo no meio de uma operação, e passar a vez a outra. É por isso que surgem race conditions e você precisa de travas. Com async, a troca é cooperativa: o controle só muda de tarefa nos pontos que você marcou com await, quando a tarefa espera por algo. Entre dois awaits, o seu código roda do começo ao fim sem interrupção. Isso torna o raciocínio mais previsível e, na prática, dispensa Lock para proteger dados dentro de uma corrotina.

Threads (preemptivo)

  • O sistema troca de thread quando quiser
  • Pode interromper no meio de uma operação
  • Exige Lock para dados compartilhados
  • Vários threads de verdade

Async (cooperativo)

  • A troca só ocorre nos pontos de await
  • Um trecho sem await roda inteiro sem parar
  • Menos travas: a troca é previsível
  • Um único thread e um event loop

Quando o async faz sentido

O async brilha exatamente no mesmo terreno das threads: tarefas I/O bound, que passam o tempo esperando rede, disco ou banco. A diferença é a escala e o estilo. Um único thread com event loop lida com milhares de conexões concorrentes sem o custo de milhares de threads, o que faz do async a escolha natural de servidores web e clientes que abrem muitas conexões ao mesmo tempo. Para cálculo puro, CPU bound, o async não ajuda em nada: como é um só thread, uma conta pesada trava o loop inteiro, e nenhuma outra tarefa avança. Assim como as threads, o async não vence o GIL para paralelismo de CPU.

Situaçãoasync ajuda?Observação
Milhares de conexões de redeSim, muitoEscala melhor que threads, sem custo por thread
Baixar dezenas de páginasSimThreads também servem; async escala mais
Servir uma API web de alto tráfegoSimModelo dominante em servidores modernos
Cálculo numérico pesadoNãoUm só thread: a conta trava o event loop
Processar imagens em massaNãoCPU bound, use processos

Async é para muito I/O concorrente; para CPU, o caminho continua sendo processos.

Teste rápido

Qual a diferença central entre a concorrência de threads e a de async?

Perguntas frequentes

Async substitui threads?
Não é bem substituir; são duas ferramentas para o mesmo tipo de problema, o I/O bound. O async escala melhor para muitas conexões e tem um modelo mais previsível, sem travas manuais. As threads são mais simples de encaixar em código já existente que não foi escrito de forma assíncrona. A escolha depende do projeto.
Async torna meu programa mais rápido em cálculos?
Não. O async roda em um único thread, então uma conta pesada bloqueia o event loop e trava todas as outras tarefas. Ele só ajuda quando há espera de I/O para aproveitar. Para acelerar cálculo, o caminho é o paralelismo com processos, como você viu no módulo de threads.
Por que async dispensa Lock que as threads exigem?
Porque a troca de tarefa só acontece nos pontos de await, que você mesmo marca. Entre dois awaits, o seu código roda do início ao fim sem interrupção, então não há duas tarefas mexendo no mesmo dado no meio de uma operação. Isso elimina boa parte das race conditions dentro de uma corrotina.
O que é exatamente o event loop?
É o coração do asyncio: um laço que mantém a lista de tarefas e decide qual roda em cada momento. Enquanto uma tarefa espera por I/O, o loop passa a vez a outra pronta. Quando a espera termina, ele retoma a primeira. Você o inicia com asyncio.run, como verá na próxima aula.
Async é difícil de aprender?
Exige entender três ideias novas: corrotina, await e event loop. Mas elas se encaixam rápido com prática. Se você já domina geradores, tem meio caminho andado, porque as corrotinas são parentes próximas deles. O curso apresenta cada peça com calma e exemplos que rodam no Playground.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.