Deadlock
Definição
Deadlock é uma situação em que duas ou mais threads (ou processos) ficam bloqueadas indefinidamente, esperando por recursos que nunca serão liberados.
Isso ocorre quando cada unidade de execução aguarda por um recurso que está preso por outra, criando um ciclo de espera impossível de resolver sem intervenção externa.
Deadlocks são comuns em sistemas concorrentes que utilizam locks, recursos compartilhados ou sistemas transacionais.
Deadlocks são difíceis de detectar porque não geram erros nem exceções — apenas travam o programa.
Por que entender Deadlocks é importante
- Identificar situações propensas a bloqueios permanentes em aplicações concorrentes.
- Evitar travamentos que não geram erro direto, mas impedem o progresso do programa.
- Implementar estratégias de prevenção, detecção ou recuperação de deadlocks.
Exemplo prático (com deadlock)
import threading
import time
lock_a = threading.Lock()
lock_b = threading.Lock()
def thread1():
with lock_a:
print("Thread 1: obteve lock A")
time.sleep(1)
with lock_b:
print("Thread 1: obteve lock B")
def thread2():
with lock_b:
print("Thread 2: obteve lock B")
time.sleep(1)
with lock_a:
print("Thread 2: obteve lock A")
t1 = threading.Thread(target=thread1)
t2 = threading.Thread(target=thread2)
t1.start()
t2.start()
t1.join()
t2.join()
Resultado
Thread 1: obteve lock A
Thread 2: obteve lock B
Nesse ponto, ambas as threads ficam esperando indefinidamente:
A Thread 1 espera o lock B, que está com a Thread 2.
A Thread 2 espera o lock A, que está com a Thread 1. O programa trava sem encerrar.
O ciclo do Deadlock
Thread 1: lock A --> esperando lock B
Thread 2: lock B --> esperando lock A
Nenhuma thread pode continuar.
O sistema entra em estado de bloqueio permanente.
Como evitar
Sempre adquirir os locks na mesma ordem entre as threads.
Utilizar timeout ao tentar adquirir locks (com
acquire(timeout=...)
).Evitar segurar múltiplos locks simultaneamente, quando possível.
Implementar estratégias de rollback, quando aplicável (como em bancos de dados).
Exemplo de solução com timeout
if lock_a.acquire(timeout=1):
try:
if lock_b.acquire(timeout=1):
try:
# seção crítica
pass
finally:
lock_b.release()
finally:
lock_a.release()
else:
print("Não foi possível obter locks — possível deadlock evitado.")
Embora isso não elimine a possibilidade de deadlock, permite detecção e recuperação controlada.
Sempre que múltiplas threads precisarem de mais de um lock, pense no risco de deadlock e defina uma estratégia clara de ordenação ou timeout.