Tutorial sobre Concorrência em Linguagem de Programação
Tutorial
Semáforos
Brasil
tco_semaforos
Menu de Sistemas

Semáforos

Conceitos

Um semáforo é uma estrutura de dados que consiste em um número inteiro e em uma fila que armazena descritores de tarefas. O conceito de semáforos consiste na colocação de proteções (guardas) em torno do código que acessa esta estrutura para oferecer acesso limitado aos dados [SEB 00]. Em geral, a estrutura de dados é uma fila, funcionando em regime de primeiro-a-entrar / primeiro a sair [GHE 91].

O semáforo é um mecanismo simples que pode ser usado para oferecer sincronismo de tarefas [SEB 00]. As operações em tipos de semáforos, muitas vezes não são diretas, elas são feitas por subprogramas de espera (wait) e de liberação (release).

Há um problema em semáforos, o deadlock. Este ocorre quando um processo altera o valor do semáforo e entra na região crítica, mas ocorre uma falha na saída da região porque ele foi danificado ou morto.

Em 1965 Dijkstra introduziu a noção de semáforo para impor a exclusão mútua entre processos. É uma construção de alto nível também usada para sincronizar processos. Um semáforo S é uma variável inteiro positiva sobre a qual os processos podem fazer duas operações primitivas (indivisíveis) - P(S) e V(S). P e V têm sua origem das palavras parsen (passar) e e vrygeren (liberar)). Uma vez iniciada uma das operações ela irá até o fim sem interrupções. Cada semáforo tem uma fila associada a ele, onde processos bloqueados nele esperam. As operações P e V são definidas como segue:

I
text
(X)
  1. P(S) : se S >= 1 então S:=S-1
  2.  
  3.                         senão Bloqueie o processo na fila do semáforo
  4.  
  5. V(S) : se algum processo está bloqueado no semáforo S
  6.  
  7.                         então desbloquear o processo
  8.  
  9.                         senão S:=S+1

Quando uma operação V(S) é executada, um processo bloqueado é retirado da fila para execução. A disciplina de empilhamento da fila do semáforo depende da implementação. Dependendo dos valores que o semáforo pode ter, há dois tipos:

O semáforo é inicializado pelo sistema. Semáforos Binários são usados para criar exclusão mútua no acesso a recursos com uma unidade apenas, porque apenas um processo pode passar pela operação P a cada vez. Semáforos de contagem são utilizados para sincronização e controle de alocação de recursos com mais de uma unidade. O valor inicial do semáforo é igual ao número de unidades do recurso.

Java não implenta explicitamente semáforos, mas fornece meios para que ele possa ser implementado. Veja um exemplo de implementção de uma classe Semaphore.

I
ada
(X)
  1. semaphore caixa, cofrecheio, cofrevazio
  2. cofrecheio.count := 0
  3. cofrevazio.count := TAMBUF
  4. task depositar;
  5.         loop
  6.         -- depositar VALOR --
  7.         wait(cofrevazio);    { espere por um espaço no cofre}
  8.         wait(caixa);         { espere por um caixa}
  9.         DEPOSITO(VALOR);
  10.         release(caixa);      { libera o caixa }
  11.         release(cofrecheio); { aumente os espaços preenchidos}
  12.         endloop;
  13. end depositar;
  14.  
  15. task sacar;
  16.         loop
  17.         wait(cofrecheio);    { certifica-se de que o cofre não está vazio}
  18.         wait(caixa);         { espere por um caixa}
  19.         SAQUE(VALOR);
  20.         release(caixa);      { libera o caixa }
  21.         release(cofrevazio); { aumenta os espaço vazio no cofre}
  22.         -- sacar VALOR --
  23.         end loop
  24. end sacar;
(X)