Sobes.tech
Middle

Qual é a diferença entre um semáforo e um mutex?

sobes.tech IA

Resposta da IA

O semáforo é um mecanismo de sincronização generalizado utilizado para gerir o acesso a recursos limitados por múltiplos threads concorrentes. Mantém um valor inteiro que diminui ao adquirir o recurso e aumenta ao libertar. Se o valor do semáforo for zero, a tentativa de o adquirir bloqueia o thread até que outro thread liberte o recurso. Pode ser usado para limitar o número de threads a trabalhar simultaneamente.

O mutex (exclusão mútua) é um semáforo binário que pode estar num estado bloqueado ou desbloqueado. É usado para proteger secções críticas do código contra acessos simultâneos por vários threads. Apenas um thread pode adquirir o mutex de cada vez. O thread que adquiriu o mutex não pode ser interrompido por outro thread que tente adquiri-lo. Se tentar adquirir um mutex bloqueado, o thread ficará bloqueado até que seja libertado.

Diferenças principais:

Característica Semáforo Mutex
Tipo Mecanismo de sincronização generalizado Semáforo binário (caso particular de semáforo)
Valor Inteiro (>= 0) Binário (0 ou 1)
Propósito Gestão de acesso a recursos, limitação de threads Proteção de secções críticas, exclusão mútua
Proprietário Pode não ter proprietário Tem sempre proprietário (thread que o adquiriu)
Uso em iOS DispatchSemaphore Frequentemente implementado através de DispatchQueue.sync ou NSRecursiveLock em alguns cenários

Exemplo de uso de mutex para proteger uma secção crítica:

// No contexto de GCD (Grand Central Dispatch)
let serialQueue = DispatchQueue(label: "com.example.criticalSection")

serialQueue.sync {
    // Secção crítica do código
    // Apenas um thread pode estar aqui de cada vez
}

Exemplo de uso de semáforo para limitar tarefas paralelas:

// No contexto de GCD (Grand Central Dispatch)
let semaphore = DispatchSemaphore(value: 3) // Permite 3 tarefas em paralelo

DispatchQueue.global().async {
    semaphore.wait() // Diminui o valor do semáforo em 1. Bloqueia se o valor for 0.

    // Código da tarefa em paralelo
    print("Tarefa em execução")

    Thread.sleep(forTimeInterval: 1) // Simulação de trabalho

    semaphore.signal() // Aumenta o valor do semáforo em 1. Desbloqueia o thread em espera, se houver.
    print("Tarefa concluída")
}

// Pode lançar vários desses blocos. Apenas 3 irão executar-se ao mesmo tempo.