Semáforo (Semaphore)
Definição
Semáforo (Semaphore) é um mecanismo de sincronização que controla o acesso concorrente a um número limitado de recursos.
Ele funciona como um contador: cada vez que uma thread adquire o semáforo, o contador é decrementado. Quando ele chega a zero, novas threads são bloqueadas até que o recurso seja liberado.
Semáforos são especialmente úteis quando mais de uma thread pode acessar um recurso simultaneamente, mas existe um limite de capacidade — como um número máximo de conexões a um banco de dados ou de tarefas simultâneas em execução.
ℹ️ Use semáforos quando várias threads podem acessar simultaneamente, mas com limite.
Se apenas uma thread por vez deve acessar, prefira umLock
.
Objetivos do uso de Semáforos
- Limitar o número de acessos simultâneos a um recurso compartilhado.
- Evitar sobrecarga em sistemas que suportam apenas um número finito de operações paralelas.
- Controlar o fluxo de execução entre múltiplas threads sem causar condições de corrida.
- Generalizar o comportamento de
locks
: enquanto locks permitem apenas uma thread, semáforos podem permitir várias.
Exemplo prático (Python)
import threading
import time
# Permitir até 3 threads simultâneas
semaforo = threading.Semaphore(3)
def tarefa(id):
with semaforo:
print(f"Thread {id} começou")
time.sleep(1)
print(f"Thread {id} terminou")
threads = []
for i in range(5):
t = threading.Thread(target=tarefa, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
ℹ️ A instrução with semaforo
: chama internamente semaforo.acquire()
ao entrar e semaforo.release()
ao sair.
Saída esperada (ordem pode variar)
Thread 0 começou
Thread 1 começou
Thread 2 começou
Thread 0 terminou
Thread 3 começou
Thread 1 terminou
Thread 4 começou
...
Observe que apenas 3 threads rodam simultaneamente — as demais aguardam o semáforo permitir.
O ciclo de uso do Semáforo
[Contador inicial: 3]
Thread A entra → contador: 2
Thread B entra → contador: 1
Thread C entra → contador: 0
Thread D tenta entrar → BLOQUEADA
Thread A sai → contador: 1 → Thread D pode entrar
O semáforo garante que nunca mais de 3 threads executem a seção simultaneamente.
Ao liberar (
release()
), outra thread pode prosseguir.
Diferença entre Semáforo e Lock
Característica | Lock | Semáforo |
---|---|---|
Acesso simultâneo | Apenas 1 thread | Várias (limitado) |
Contador interno | Não | Sim |
Uso típico | Exclusão mútua | Controle de volume |