Os semáforos, computacionalmente falando, foram inventados por Edsger Dijkstra em 1965, um famoso cientista holandês da computação. Ele propôs um mecanismo de coordenação eficiente e flexível para o controle da exclusão mútua várias tarefas. Apesar de antigo, o semáforo continua sendo o mecanismo de sincronização mais utilizado na construção de aplicações concorrentes. A ideia é a mesma de um semáforo de trânsito, cada carro seria um processo/task e assim que o sinal estiver verde, o carro é liberado. No nosso caso, a task é liberada.
Um semáforo é um mecanismo que tem como função o controle e sincronização de acesso a recursos compartilhados. Eles resolvem, por exemplo, o problema de exclusão mútua. Temos dois tipos de operações principais de acesso que ocorrerem: trancamento (Down) e destrancamento (Up) na execução de tarefas.
Essas operações são geralmente realizadas pelo núcleo do sistema operacional, como System Calls. Na execução dessas operações não devem ocorrer acessos concorrentes ao semáforo para evitar uma disputa sobre o mesmo.
Existem dois tipos de semáforos: binário (bloqueio mutex – 0 ou 1) e contagem ou genérico. No binário, por exemplo, assim que um recurso entre em sua região crítica, ele é trancado, para que nenhum outro processo possa entrar na mesma. Assim que o processo crítico acabe, o recurso é destrancado. Com isso ele assume apenas dois valores: 0 para trancado e 1 para livre. No de contagem, controlamos o acesso de um recurso que possui várias instâncias e pode assumir qualquer valor.