image

Bootcamps ilimitados + curso de inglês para sempre

80
%OFF
Article image
Fernanda Araujo
Fernanda Araujo23/06/2025 12:00
Compartilhe

Paradigmas de Linguagens de Programação em Python: Python concorrente (Part. 11)

    A programação concorrente é essencial para lidar com tarefas simultâneas e melhorar o desempenho de aplicações que precisam fazer mais de uma coisa ao mesmo tempo. Neste artigo, vamos explorar como Python trata a concorrência, os conceitos-chave envolvidos, e como aplicar isso de forma eficaz — sem cair em armadilhas comuns.

    Para ilustrar esse processo, vamos imaginar que somos Nico Robin, a arqueóloga de One Piece, tentando decifrar os antigos Poneglyphs. Assim como um desenvolvedor precisa entender, executar e corrigir seu código, Robin precisa interpretar símbolos, prever falhas e reagir a imprevistos durante a tradução de textos milenares.

    ⚙️ O que é Programação Concorrente?

    Concorrência é a capacidade de um programa de executar várias tarefas "ao mesmo tempo", mesmo em ambientes com apenas um núcleo de processamento. Isso é feito por meio do intercalamento inteligente de tarefas (threads, processos ou corrotinas).

    Diferente da paralelização (que envolve múltiplas CPUs), a concorrência se foca na organização lógica do programa para que tarefas sejam coordenadas eficientemente, compartilhando tempo de execução.

    🧠 Características do Paradigma Concorrente

    • Execução intercalada: tarefas podem suspender e retomar sem bloqueio total do programa.
    • Gerenciamento de tarefas: envolve múltiplas unidades de execução (threads, processos ou corrotinas).
    • Compartilhamento de recursos: exige controle cuidadoso de estado compartilhado.
    • Sincronização: evita condições de corrida (race conditions) e inconsistências.

    🐍 Como Python executa código em Paradigma Concorrente

    Python oferece diversas abordagens para concorrência, cada uma com suas características e limitações, especialmente por conta do GIL (Global Interpreter Lock):

    🔸 1. Threading (concorrência com threads)

    Usado para I/O concorrente (espera por arquivos, rede etc.), mas limitado em paralelismo real devido ao GIL.

    python
    
    import threading
    
    def ler_documento():
      print("Lendo documentos do século perdido...")
    
    thread = threading.Thread(target=ler_documento)
    thread.start()
    thread.join()
    

    🔸 2. Multiprocessing (processos reais)

    Cada processo roda em um núcleo separado — ideal para tarefas de CPU.

    python
    
    from multiprocessing import Process
    
    def decifrar_rocha():
      print("Decifrando rochas lunares...")
    
    p = Process(target=decifrar_rocha)
    p.start()
    p.join()
    

    🔸 3. Asyncio (corrotinas assíncronas)

    Ideal para grande número de tarefas de I/O assíncronas (como múltiplas conexões).

    python
    
    import asyncio
    
    async def buscar_fragmento():
      print("Buscando fragmento do Poneglyph...")
      await asyncio.sleep(1)
      print("Fragmento encontrado!")
    
    asyncio.run(buscar_fragmento())
    

    🔄 Gerenciamento de Estado e Escopo em Python Concorrente

    🔐 Estado Compartilhado (e seus perigos)

    Se várias tarefas acessam e modificam o mesmo dado ao mesmo tempo, o risco de corrupção é alto.

    python
    
    import threading
    
    
    contador = 0
    
    
    def copiar_simbolo():
      global contador
      for _ in range(100000):
          contador += 1  # Vários "braços" alterando o mesmo dado
    
    
    threads = [threading.Thread(target=copiar_simbolo) for _ in range(2)]
    [t.start() for t in threads]
    [t.join() for t in threads]
    
    
    print(contador)  # Resultado inesperado! Fragmentos perdidos.
    

    Esse é um clássico problema de condição de corrida. Para evitar que Robin escreva com todos os braços no mesmo lugar ao mesmo tempo, usamos um "bloqueio" (lock) para que apenas um braço por vez escreva com segurança.

    ✅ Solução: Uso de locks

    python
    
    lock = threading.Lock()
    
    
    def copiar_com_cuidado():
      global contador
      for _ in range(100000):
          with lock:  # Apenas um braço pode escrever por vez
              contador += 1
    
    
    threads = [threading.Thread(target=copiar_com_cuidado) for _ in range(2)]
    [t.start() for t in threads]
    [t.join() for t in threads]
    
    
    print(contador)  # Agora o total está correto e os símbolos preservados.
    

    Com controle sincronizado, cada tarefa tem sua vez de alterar o estado, como se Robin organizasse uma fila invisível para seus próprios braços — garantindo que nenhum símbolo seja perdido no processo.

    📌 Boas Práticas para Programação Concorrente em Python

    ✅ Use multiprocessing para tarefas intensivas de CPU

    ✅ Use asyncio para muitas tarefas de I/O não bloqueantes

    ✅ Evite estado global compartilhado entre threads/processos

    ✅ Prefira estruturas seguras para concorrência (Queue, Lock, Event)

    ✅ Divida o problema em tarefas isoladas e independentes

    ✅ Sempre pense em possíveis condições de corrida

    ✅ Faça testes em ambientes concorrentes, pois bugs podem ser não determinísticos

    🔚 Conclusão

    Adotar o paradigma concorrente em Python é um passo estratégico para quem busca construir aplicações escaláveis, responsivas e preparadas para o mundo real. Ao dominar recursos como threads, processos e programação assíncrona, o desenvolvedor supera os limites do GIL e transforma tarefas isoladas em sistemas que cooperam com eficiência.

    Assim como Robin, que lê vários idiomas antigos ao mesmo tempo e conecta fragmentos espalhados para formar uma revelação completa, programar de forma concorrente é orquestrar múltiplas ações em harmonia. Cada tarefa, como um braço da Robin, atua em paralelo — e é essa coordenação precisa que permite transformar o caos em clareza, e a lentidão em desempenho.

    image

    Compartilhe
    Recomendados para você
    Deal Group - AI Centric .NET
    Randstad - Análise de Dados
    BairesDev - Machine Learning Training
    Comentários (1)
    DIO Community
    DIO Community - 23/06/2025 17:05

    Fernanda, o artigo sobre Programação Concorrente em Python ficou excelente! Você fez uma ótima analogia com a Nico Robin e os Chapéus de Palha, tornando o conceito de concorrência muito mais acessível e intuitivo. Usar essa metáfora para explicar como tarefas independentes podem avançar simultaneamente é uma maneira criativa e eficaz de ensinar um conceito tão técnico.

    Eu gostei muito da clareza ao apresentar as diferentes formas de concorrência em Python, como threading, asyncio e multiprocessing. A explicação sobre o uso de asyncio para tarefas assíncronas e a comparação entre concorrência e paralelismo também foram bem feitas. Sua abordagem permite que iniciantes no tema consigam entender como organizar e dividir tarefas de maneira eficiente.

    Minha pergunta para você é: em quais tipos de aplicações você acredita que o uso de concorrência em Python pode ser mais vantajoso em comparação com o uso de programação sequencial? Existem casos específicos onde você recomendaria fortemente o uso de concorrência para melhorar a performance ou a escalabilidade?