Programação Multithread em Python: Concorrência Eficiente
Executar várias threads é semelhante a rodar vários programas simultaneamente, mas com vantagens:
- Threads compartilham o mesmo espaço de dados do processo principal, facilitando comunicação.
- São light-weight processes – menor overhead de memória que processos.
Uma thread tem início, sequência de execução e fim, com um ponteiro de instrução. Pode ser preemptada (interrompida) ou colocada em espera (sleep/yield).
Iniciando Nova Thread (módulo thread – baixo nível)
thread.start_new_thread(funcao, args[, kwargs])
Retorna imediatamente; a thread filha executa funcao(*args, **kwargs) e termina quando a função retorna.
Exemplo
#!/usr/bin/python
import thread, time
def imprimir_tempo(nome, atraso):
cont = 0
while cont < 5:
time.sleep(atraso)
cont += 1
print(f"{nome}: {time.ctime(time.time())}")
try:
thread.start_new_thread(imprimir_tempo, ("Thread-1", 2))
thread.start_new_thread(imprimir_tempo, ("Thread-2", 4))
except:
print("Erro ao iniciar thread")
while True:
pass # mantém programa vivo
Limitação: O módulo thread é limitado; prefira o módulo threading (alto nível).
Módulo threading
Fornece suporte avançado. Métodos extras:
threading.active_count()– threads ativas.threading.current_thread()– thread atual.threading.enumerate()– lista de threads ativas.
Classe Thread
run()– ponto de entrada (sobrescreva).start()– inicia a thread chamandorun().join([timeout])– aguarda término.is_alive()– verifica se ainda executa.getName()/setName()– nome da thread.
Criando Thread com threading
- Subclasse
threading.Thread. - Sobrescreva
__init__para argumentos extras. - Sobrescreva
runcom a lógica. - Instancie e chame
start().
Exemplo
#!/usr/bin/python
import threading, time
class MinhaThread(threading.Thread):
def __init__(self, thread_id, nome, contador):
super().__init__()
self.thread_id = thread_id
self.nome = nome
self.contador = contador
def run(self):
print(f"Iniciando {self.nome}")
imprimir_tempo(self.nome, self.contador, 5)
print(f"Saindo {self.nome}")
def imprimir_tempo(nome, contador, atraso):
while contador:
time.sleep(atraso)
print(f"{nome}: {time.ctime(time.time())}")
contador -= 1
t1 = MinhaThread(1, "Thread-1", 1)
t2 = MinhaThread(2, "Thread-2", 2)
t1.start()
t2.start()
print("Saindo da thread principal")
Sincronização com Locks
Use threading.Lock() para evitar condições de corrida.
lock.acquire(blocking=True)– obtém lock (bloqueia seTrue).lock.release()– libera lock.
Exemplo com Lock
lock = threading.Lock()
class MinhaThread(threading.Thread):
def run(self):
print(f"Iniciando {self.name}")
lock.acquire()
imprimir_tempo(self.name, self.counter, 3)
lock.release()
threads = []
for i in range(2):
t = MinhaThread(i+1, f"Thread-{i+1}", i+1)
t.start()
threads.append(t)
for t in threads:
t.join()
print("Saindo da thread principal")
Fila de Prioridade Multithread (queue.Queue)
Fila thread-safe para comunicação produtor-consumidor.
q.put(item)– insere item.q.get()– remove e retorna item.q.qsize(),empty(),full()– status.
Exemplo Produtor-Consumidor
import queue, threading, time
fila = queue.Queue(10)
lock_fila = threading.Lock()
exit_flag = 0
class Worker(threading.Thread):
def __init__(self, nome, fila):
super().__init__()
self.nome = nome
self.fila = fila
def run(self):
print(f"Iniciando {self.nome}")
while not exit_flag:
lock_fila.acquire()
if not self.fila.empty():
dado = self.fila.get()
lock_fila.release()
print(f"{self.nome} processando {dado}")
else:
lock_fila.release()
time.sleep(1)
print(f"Saindo {self.nome}")
# Cria threads
threads = [Worker(f"Thread-{i}", fila) for i in range(3)]
for t in threads: t.start()
# Preenche fila
lock_fila.acquire()
for palavra in ["Um", "Dois", "Três", "Quatro", "Cinco"]:
fila.put(palavra)
lock_fila.release()
# Aguarda fila esvaziar
while not fila.empty():
pass
exit_flag = 1
for t in threads: t.join()
print("Saindo da thread principal")
Nota: Em Python 3, use queue (minúsculo) e métodos is_alive(), active_count(), etc.
python
- Formação de Rosca vs Laminação de Rosca: Entendendo as Diferenças Principais
- Dominando Tipos de Dados em Python: Guia Prático
- Dominando Operadores em Python: Guia Completo
- Dominando a Declaração Pass em Python: Guia Prático
- Dominando Argumentos de Funções em Python: Parâmetros Posicionais, Nomeados e Padrão
- Dominando Dicionários em Python: Criação, Manipulação e Técnicas Avançadas
- Dominando Programação Orientada a Objetos em Python: Classes, Herança, Encapsulamento e Polimorfismo
- Programação de Rede em Python: Sockets e Protocolos Avançados
- Programação de Extensões Python com C: Criando Módulos Nativos Rápidos
- Dominando o Ciclo de Rosqueamento Fanuc G76: Guia Completo para Operadores CNC