Threading no Python: threads, locks e concorrência

Atualizado em: 20/08/2026
Tempo de leitura: 8 minutos
Problemas de travamento com threading em scripts Python

Você já sentiu a frustração de rodar um código e, de repente, a interface parar de responder ou o terminal parecer congelado? Esse problema é extremamente comum entre desenvolvedores que estão saindo do básico. O motivo principal é que, por padrão, o Python executa as instruções de forma sequencial, uma após a outra. Se uma tarefa demora muito, como baixar um arquivo pesado ou processar milhares de dados, todo o restante do programa precisa esperar. É aqui que entra o conceito de Threading no Python, uma técnica poderosa para realizar múltiplas tarefas simultaneamente e evitar que suas aplicações travem.

Por que seu script trava? Entendendo o fluxo sequencial

Para entender o Threading no Python, primeiro precisamos olhar para como um programa padrão funciona. Imagine que você está seguindo uma receita de bolo. Você bate a massa, coloca no forno e fica parado na frente da porta do fogão esperando 40 minutos até terminar, sem poder lavar a louça ou arrumar a mesa. Na programação, chamamos isso de execução síncrona ou sequencial.

Quando você trabalha com python para automação, é muito comum precisar lidar com operações de Entrada e Saída (I/O). Se o seu script precisa ler um arquivo grande ou fazer uma requisição web, ele envia o pedido e fica “bloqueado” aguardando a resposta. Durante esse tempo de espera, o processador não está fazendo nada útil, mas o seu programa parece travado para o usuário final.

O que é Threading no Python e como ele funciona?

Uma “thread” (ou linha de execução) é a menor unidade de processamento que pode ser gerenciada pelo sistema operacional. O Threading no Python permite que seu programa execute várias dessas linhas ao mesmo tempo dentro do mesmo processo. Retomando o exemplo da cozinha: com threads, enquanto o bolo está no forno, você pode começar a lavar a louça. Você ainda é uma única pessoa (um processo), mas está gerenciando múltiplas tarefas alternando entre elas rapidamente.

É importante diferenciar o threading do multiprocessamento. Enquanto o multiprocessamento utiliza múltiplos núcleos da CPU de forma paralela, o threading compartilha o mesmo espaço de memória. No Python, existe um mecanismo chamado Global Interpreter Lock (GIL). O GIL garante que apenas uma thread execute código Python por vez. Isso pode parecer uma limitação, mas para tarefas que envolvem espera (como rede ou leitura de disco), o threading é extremamente eficiente.

Quando usar Threading vs Asyncio?

Muitos iniciantes ficam confusos entre usar threads ou o módulo asyncio no python. A regra de ouro é simples: se o seu programa gasta muito tempo esperando por algo externo (rede, banco de dados, arquivos), o threading é uma excelente escolha. Se você precisa gerenciar milhares de conexões simultâneas de forma ultra leve, o asyncio leva a vantagem.

O threading é baseado em preempção, o que significa que o sistema operacional decide quando alternar entre as threads. Já o modo assíncrono é cooperativo: o próprio código diz quando pode ceder o controle. Para quem está começando e quer resolver problemas de travamento em scripts simples ou interfaces gráficas, o módulo threading costuma ser mais intuitivo.

A Anatomia de uma Thread no Python

Para começar a usar threads, o Python fornece um módulo nativo chamado threading. Não é necessário instalar nada extra, pois ele faz parte das bibliotecas em python padrão que já vêm com o interpretador. O objeto principal que utilizaremos é a classe Thread.

Os passos básicos para criar uma thread são:

  • Importar o módulo threading.
  • Definir a função que realizará a tarefa demorada.
  • Criar uma instância de Thread passando a função como alvo.
  • Iniciar a thread com o método .start().

Exemplo prático: Simulando um download sem travar

Vamos ver um exemplo de como o Threading no Python resolve o problema de congelamento. Imagine um script que precisa baixar três arquivos grandes. Sem threads, ele baixaria o primeiro, depois o segundo e só então o terceiro. Com threads, iniciamos os três processos quase ao mesmo tempo.

import threading
import time

def baixar_arquivo(nome):
    print(f"Iniciando download de {nome}...")
    time.sleep(3)  # Simulando uma tarefa demorada
    print(f"Download de {nome} finalizado!")

# Criando as threads
t1 = threading.Thread(target=baixar_arquivo, args=("Relatorio.pdf",))
t2 = threading.Thread(target=baixar_arquivo, args=("Imagem.png",))

# Iniciando as threads
t1.start()
t2.start()

print("O programa principal continua rodando normalmente!")

# Aguardando as threads terminarem para fechar o programa
t1.join()
t2.join()
print("Todos os downloads foram concluídos.")

Observe o uso do método .join(). Ele serve para dizer ao programa principal: “espere aqui até que esta thread termine antes de continuar”. Sem o join, o programa poderia encerrar antes mesmo dos downloads serem concluídos.

Evitando travamentos em Interfaces Gráficas

Um dos maiores usos do Threading no Python é na criação de softwares com janelas. Ao criar interfaces gráficas com tkinter no python, a janela roda em um loop infinito chamado MainLoop. Se você executa uma função pesada diretamente em um botão, esse loop para, e a janela exibe a mensagem “Não respondendo”.

A solução é sempre disparar a lógica pesada em uma thread separada. Dessa forma, o MainLoop da interface continua rodando a 60 quadros por segundo, mantendo os botões clicáveis e as animações fluidas, enquanto o processamento ocorre “por baixo dos panos”.

Os perigos do Threading: Race Conditions

Nem tudo são flores no mundo da concorrência. Quando múltiplas threads tentam modificar a mesma variável ao mesmo tempo, ocorre o que chamamos de Race Condition (Condição de Corrida). Imagine que duas threads tentam aumentar o valor de um contador simultaneamente. Elas podem ler o mesmo valor inicial e salvar o mesmo resultado, fazendo com que um dos incrementos seja perdido.

Para evitar isso, usamos um objeto chamado Lock (tranca). Quando uma thread vai mexer em um dado sensível, ela “tranca” o acesso. Outras threads que tentarem mexer no mesmo dado terão que esperar o desbloqueio. É uma forma de garantir a integridade dos dados, especialmente importante quando usamos dicionarios em python ou listas compartilhadas.

Tratamento de erros em Threads

Um detalhe importante é que, se uma thread secundária sofrer um erro e “morrer”, ela não necessariamente derruba o programa principal. Isso pode dificultar o rastreio de bugs. Para gerenciar isso, é recomendável usar blocos de try except em python dentro da função que a thread executa. Caso contrário, a thread apenas para silenciosamente e você nunca saberá o que deu errado.

Além disso, o uso excessivo de mensagens no console pode ficar confuso com várias threads rodando. Nestes casos, utilizar o logging python é muito mais eficaz do que o comando print, pois o logging é thread-safe e permite identificar qual thread gerou cada mensagem.

Melhores Práticas para Threading no Python

Para garantir que seu código seja robusto e escalar bem, siga estas recomendações ao usar Threading no Python:

  • Use ThreadPoolExecutor: Para gerenciar muitas threads, em vez de criar uma por uma manualmente, prefira o concurrent.futures.ThreadPoolExecutor. Ele gerencia um “conjunto” de threads para você.
  • Threads como Daemon: Se você tem uma thread que deve rodar apenas enquanto o programa principal estiver vivo (como um monitor de logs), defina daemon=True. Isso garante que o Python feche a thread automaticamente quando o script encerrar.
  • Evite Computação Intensiva: Lembra do GIL? Se o seu problema for cálculos matemáticos pesados, o threading não ajudará. Use bibliotecas especializadas como numpy no python ou o módulo multiprocessing.
  • Documentação: Sempre descreva o que cada thread faz usando docstrings python para que outros desenvolvedores entendam a lógica assíncrona.

O desenvolvimento moderno exige que as aplicações sejam responsivas. Dominar o threading permite que você saia do nível de scripts básicos para criar ferramentas profissionais, bots de automação eficientes e sistemas que realmente aproveitam o tempo de processamento disponível.

Para se aprofundar mais nos detalhes técnicos da implementação, a documentação oficial do Python Software Foundation oferece um guia completo sobre todas as classes e métodos disponíveis no módulo de threading.

Perguntas Frequentes

O threading deixa o Python mais rápido?

Depende. Para tarefas de I/O (espera), sim. Para tarefas de CPU (cálculos), não, devido ao GIL.

Quantas threads posso criar no meu script?

Não há um limite rígido, mas criar milhares de threads consome muita memória RAM e pode degradar a performance do sistema operacional.

Qual a diferença entre start() e run() no threading?

O start() inicia a função em uma nova thread. O run() apenas executa a função na thread atual, de forma sequencial.

O que acontece se eu esquecer o join()?

O programa principal continuará sua execução. Se o script terminar, as threads não-daemônicas manterão o processo aberto até finalizarem.

Posso usar threads para fazer Web Scraping?

Sim! É uma das melhores aplicações, permitindo baixar várias páginas simultaneamente em vez de uma por uma.

Como parar uma thread à força no Python?

O módulo threading não oferece uma forma segura de “matar” uma thread. O ideal é usar uma variável de controle (flag) que a própria thread verifica para encerrar o loop.

O threading funciona no Python para celular?

Sim, o suporte a threads é mantido em implementações de python no celular, como o Kivy ou BeeWare.

É seguro compartilhar listas entre threads?

Listas e dicionários são thread-safe para operações atômicas simples, mas para modificações complexas (ler, alterar e salvar), você deve usar um Lock.

Agora que você entendeu como o threading funciona, que tal aplicar esse conhecimento em um projeto real? Tente criar um script de automação que realiza múltiplas tarefas de limpeza de arquivos sem travar a interface do usuário!

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    A developer typing code on a laptop with a Python book beside in an office.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ftplib no Python: FTP e FTPS seguros

    Aprenda ftplib no Python para listar, baixar e enviar arquivos por FTP ou FTPS com TLS, timeouts, limites, retomada e

    Ler mais

    Tempo de leitura: 5 minutos
    21/08/2026
    Rack de servidores representando um endpoint criado com xmlrpc.server no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    xmlrpc.server: crie servidores XML-RPC

    Aprenda xmlrpc.server no Python para criar servidores XML-RPC, registrar funções, limitar métodos e caminhos e evitar exposição insegura.

    Ler mais

    Tempo de leitura: 6 minutos
    21/08/2026
    Cabos conectados a servidor representando chamadas remotas com xmlrpc.client no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    xmlrpc.client no Python: chamadas RPC

    Aprenda xmlrpc.client no Python para chamar serviços XML-RPC, tratar Fault e ProtocolError, usar TLS, tipos compatíveis e limites seguros.

    Ler mais

    Tempo de leitura: 4 minutos
    21/08/2026
    Código de erro sobre dados binários representando falhas tratadas com urllib.error no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    urllib.error no Python: trate falhas HTTP

    Aprenda urllib.error no Python para tratar URLError, HTTPError, downloads incompletos, retries seletivos e diagnósticos de rede mais claros.

    Ler mais

    Tempo de leitura: 6 minutos
    21/08/2026
    Teclas com a palavra HTML representando entidades HTML no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    html.entities: converta entidades HTML

    Aprenda html.entities no Python para consultar entidades HTML, converter nomes e code points e evitar confundir decoding com sanitização.

    Ler mais

    Tempo de leitura: 7 minutos
    21/08/2026
    Pasta com arquivos representando tipos MIME identificados com mimetypes no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    mimetypes: detecte tipos MIME de arquivos

    Aprenda mimetypes no Python para identificar tipos de arquivos, validar uploads e gerar headers HTTP com mais segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    20/08/2026