Semáforos em Sistemas Operacionais

Uma demonstração interativa de sincronização entre processos/threads. O semáforo controla o acesso a uma seção crítica, impedindo que múltiplas execuções usem simultaneamente um recurso que deve ser exclusivo.

1. Conceito

Um semáforo é uma variável de sincronização manipulada por operações atômicas. Em sua forma mais simples, um semáforo binário possui valor 1 quando o recurso está disponível e 0 quando está ocupado.

wait(S) / P() Tenta adquirir o recurso. Se S = 0, o processo pode ser bloqueado.
signal(S) / V() Libera o recurso e permite que outro processo continue.
Seção crítica Trecho de código que acessa dados ou recursos compartilhados.

2. Estado do semáforo

1

Recurso disponível. Um processo pode executar wait(S).

3. Processos, fila e seção crítica

Nenhum processo dentro da seção crítica.
READY / PRONTOS
BLOCKED / BLOQUEADOS
READYaguarda CPU
RUNNINGexecutando
BLOCKEDaguarda recurso

4. O que acontece a cada operação?

5. Semáforo binário x contador

Capacidade do recurso

No semáforo contador, o valor pode representar a quantidade de instâncias disponíveis de um recurso, como 3 impressoras, 5 conexões de banco de dados ou N buffers.

6. Pseudocódigo clássico

// semáforo inicialmente livre
semaphore S = 1;

processo() {
    wait(S);     // tenta entrar

    // ===== SEÇÃO CRÍTICA =====
    acessar_recurso_compartilhado();

    signal(S);   // libera o recurso
}

7. Exemplo conceitual em JavaScript

class Semaphore {
  constructor(value = 1) {
    this.value = value;
    this.queue = [];
  }

  async wait() {
    if (this.value > 0) {
      this.value--;
      return;
    }
    await new Promise(resolve =>
      this.queue.push(resolve)
    );
  }

  signal() {
    const next = this.queue.shift();
    next ? next() : this.value++;
  }
}

Observação: JavaScript no navegador não é um sistema operacional, mas o padrão acima ajuda a visualizar a mesma ideia de controlar concorrência em tarefas assíncronas.

8. Relação com os estados de processos do S.O.

Quando um processo chama wait(S) e o recurso está indisponível, ele não precisa ficar gastando CPU verificando continuamente o semáforo. O sistema pode colocá-lo no estado Blocked. Quando outro processo chama signal(S), um processo bloqueado pode voltar para Ready e, posteriormente, ser escalonado para Running.

ReadyTem condições de executar, mas aguarda CPU.
RunningEstá executando instruções na CPU.
BlockedAguarda evento ou recurso, como um semáforo.