Um semáforo é um conceito de programação usado com freqüência para resolver problemas de multiencadeamento. Minha pergunta para a comunidade:
O que é um semáforo e como você o usa?
multithreading
concurrency
semaphore
bmurphy1976
fonte
fonte
Respostas:
Pense nos semáforos como seguranças de uma boate. Há um número dedicado de pessoas que são permitidas no clube de uma só vez. Se o clube estiver cheio, ninguém poderá entrar, mas assim que uma pessoa sair, outra pessoa poderá entrar.
É simplesmente uma maneira de limitar o número de consumidores para um recurso específico. Por exemplo, para limitar o número de chamadas simultâneas para um banco de dados em um aplicativo.
Aqui está um exemplo muito pedagógico em C # :-)
fonte
O artigo Mutexes e semáforos desmistificados por Michael Barr é uma excelente introdução ao que diferencia mutexes e semáforos, e quando eles devem e não devem ser usados. Trecho de vários parágrafos-chave aqui.
O ponto principal é que mutexes devem ser usados para proteger recursos compartilhados, enquanto semáforos devem ser usados para sinalização. Geralmente, você não deve usar semáforos para proteger recursos compartilhados, nem mutexes para sinalização. Há problemas, por exemplo, com a analogia do segurança em termos de uso de semáforos para proteger recursos compartilhados - você pode usá-los dessa maneira, mas pode dificultar o diagnóstico de bugs.
...
Nesse ponto, uma analogia interessante é feita usando a idéia de chaves do banheiro como proteção de recursos compartilhados - o banheiro. Se uma loja tiver um único banheiro, uma única chave será suficiente para proteger esse recurso e impedir que várias pessoas o usem simultaneamente.
Se houver vários banheiros, pode-se ficar tentado a digitá-los da mesma maneira e criar várias chaves - isso é semelhante a um semáforo sendo mal utilizado. Quando você tem uma chave, na verdade não sabe qual banheiro está disponível, e se você seguir esse caminho, provavelmente acabará usando mutexes para fornecer essas informações e garantir que não toma um banheiro já ocupado .
Um semáforo é a ferramenta errada para proteger vários dos mesmos recursos, mas é quantas pessoas pensam e o usam. A analogia do segurança é distintamente diferente - não há vários do mesmo tipo de recurso; em vez disso, existe um recurso que pode aceitar vários usuários simultâneos. Suponho que um semáforo possa ser usado nessas situações, mas raramente existem situações do mundo real em que a analogia realmente se mantém - é mais frequente que existam vários do mesmo tipo, mas ainda recursos individuais, como os banheiros, que não podem ser usados por aqui.
...
...
Aqui, é importante ressaltar que os mutexes interferem de maneira ruim nos sistemas operacionais em tempo real, causando inversão de prioridade, onde uma tarefa menos importante pode ser executada antes de uma tarefa mais importante por causa do compartilhamento de recursos. Em resumo, isso acontece quando uma tarefa de prioridade mais baixa usa um mutex para capturar um recurso, A, e tenta capturar B, mas é interrompida porque B não está disponível. Enquanto espera, uma tarefa de maior prioridade surge e precisa de A, mas já está vinculada e por um processo que nem está em execução porque está aguardando B. Há muitas maneiras de resolver isso, mas na maioria das vezes é corrigido alterando o mutex e o gerenciador de tarefas. O mutex é muito mais complexo nesses casos do que um semáforo binário,
...
Mutex: compartilhamento de recursos
Semáforo: sinalização
Não use um para o outro sem considerar cuidadosamente os efeitos colaterais.
fonte
Mutex: acesso de membro exclusivo a um recurso
Semáforo: acesso de n membros a um recurso
Ou seja, um mutex pode ser usado para sincronizar o acesso a um contador, arquivo, banco de dados, etc.
Um sempahore pode fazer a mesma coisa, mas suporta um número fixo de chamadas simultâneas. Por exemplo, posso agrupar minhas chamadas de banco de dados em um semáforo (3) para que meu aplicativo multithread chegue ao banco de dados com no máximo três conexões simultâneas. Todas as tentativas serão bloqueadas até que um dos três slots seja aberto. Eles fazem coisas como fazer uma otimização ingênua muito, muito fácil.
fonte
Considere um táxi que pode acomodar um total de 3 pessoas ( traseira ) +2 ( dianteira ), incluindo o motorista. Portanto, a
semaphore
permite apenas 5 pessoas dentro de um carro por vez. E ummutex
permite apenas 1 pessoa em um único assento do carro.Portanto,
Mutex
é permitir acesso exclusivo a um recurso ( como um encadeamento do SO ) enquanto aSemaphore
é permitir acesso a um número n de recursos por vez.fonte
@Craig:
Isso não está restrito a apenas um segmento. Um semáforo pode ser configurado para permitir que um número fixo de threads acesse um recurso.
fonte
O semáforo também pode ser usado como ... semáforo. Por exemplo, se você tiver vários dados de enfileiramento de processos em uma fila e apenas uma tarefa consumindo dados da fila. Se você não deseja que sua tarefa consumidora pesquise constantemente na fila os dados disponíveis, use o semáforo.
Aqui o semáforo não é usado como um mecanismo de exclusão, mas como um mecanismo de sinalização. A tarefa de consumo está aguardando no semáforo. A tarefa de produção está lançando no semáforo.
Dessa forma, a tarefa consumidora é executada quando e somente quando há dados a serem desenfileirados
fonte
Existem dois conceitos essenciais para a criação de programas concorrentes - sincronização e exclusão mútua. Veremos como esses dois tipos de bloqueios (semáforos são geralmente um tipo de mecanismo de bloqueio) nos ajudam a obter sincronização e exclusão mútua.
Um semáforo é uma construção de programação que nos ajuda a obter simultaneidade, implementando a sincronização e a exclusão mútua. Os semáforos são de dois tipos, Binário e Contagem.
Um semáforo tem duas partes: um contador e uma lista de tarefas aguardando para acessar um recurso específico. Um semáforo executa duas operações: aguarde (P) [é como adquirir um bloqueio] e libere (V) [semelhante à liberação de um bloqueio] - essas são as únicas duas operações que se pode executar em um semáforo. Em um semáforo binário, o contador logicamente varia entre 0 e 1. Você pode pensar nele como sendo semelhante a um bloqueio com dois valores: aberto / fechado. Um semáforo de contagem possui vários valores para contagem.
O que é importante entender é que o contador de semáforo controla o número de tarefas que não precisam ser bloqueadas, ou seja, elas podem progredir. As tarefas são bloqueadas e adicionadas à lista de semáforos somente quando o contador é zero. Portanto, uma tarefa é adicionada à lista na rotina P () se não puder progredir e "liberada" usando a rotina V ().
Agora, é bastante óbvio ver como os semáforos binários podem ser usados para resolver a sincronização e exclusão mútua - eles são essencialmente bloqueios.
ex. Sincronização:
No exemplo acima, B2 só pode ser executado após a conclusão de B1. Digamos que o encadeamento A seja executado primeiro - chegue a sem.P () e aguarde, pois o contador é 0 (fechado). O segmento B aparece, termina B1 e libera o segmento A - que completa B2. Então, alcançamos a sincronização.
Agora, vamos examinar a exclusão mútua com um semáforo binário:
A exclusão mútua também é bastante simples - m1 e m2 não podem entrar na seção crítica ao mesmo tempo. Portanto, cada thread está usando o mesmo semáforo para fornecer exclusão mútua para suas duas seções críticas. Agora, é possível ter maior concorrência? Depende das seções críticas. (Pense em como mais alguém poderia usar semáforos para obter exclusão mútua. Dica dica: preciso necessariamente usar apenas um semáforo?)
Semáforo de contagem: um semáforo com mais de um valor. Vejamos o que isso implica - um bloqueio com mais de um valor? Tão aberto, fechado e ... hmm. De que uso um bloqueio de vários estágios na exclusão ou sincronização mútua?
Vamos pegar o mais fácil dos dois:
Sincronização usando um semáforo de contagem: Digamos que você tenha 3 tarefas - nº 1 e 2 que deseja executar após 3. Como você projetaria sua sincronização?
Portanto, se o seu semáforo começar fechado, você garante que o bloco t1 e t2 seja adicionado à lista do semáforo. Então, vem toda a T3 importante, encerra seus negócios e libera T1 e T2. Em que ordem eles são libertados? Depende da implementação da lista do semáforo. Pode ser FIFO, pode ser baseada em alguma prioridade particular, etc. (Nota: pense em como você organizaria seus P e V; s se você desejasse que t1 e t2 fossem executados em alguma ordem específica e se não estivesse ciente da implementação do semáforo)
(Descubra: O que acontece se o número de V's for maior que o número de P's?)
Exclusão mútua Usando semáforos de contagem: eu gostaria que você construísse seu próprio pseudocódigo para isso (faz você entender melhor as coisas!) - mas o conceito fundamental é este: um semáforo de contagem de counter = N permite que N tarefas entrem livremente na seção crítica . O que isso significa é que você tem N tarefas (ou threads, se quiser) entram na seção crítica, mas a N + 1ª tarefa é bloqueada (entra na nossa lista de tarefas bloqueadas favoritas) e só é liberada quando alguém V é o semáforo pelo menos uma vez. Assim, o contador de semáforo, em vez de balançar entre 0 e 1, agora passa entre 0 e N, permitindo que N tarefas entrem e saiam livremente, bloqueando ninguém!
Agora, caramba, por que você precisaria de uma coisa tão estúpida? Não é o ponto de exclusão mútua não permitir que mais de um indivíduo acesse um recurso? (Dica Dica ... Você nem sempre tem apenas uma unidade no seu computador, tem ...?)
Pensar : a exclusão mútua é alcançada por ter um semáforo de contagem sozinho? E se você tiver 10 instâncias de um recurso e 10 threads (através do semáforo de contagem) e tentar usar a primeira instância?
fonte
Um semáforo é um objeto que contém um número natural (ou seja, um número inteiro maior ou igual a zero) no qual duas operações de modificação são definidas. Uma operação,
V
adiciona 1 ao natural. A outra operação,P
diminui o número natural em 1. Ambas as atividades são atômicas (ou seja, nenhuma outra operação pode ser executada ao mesmo tempo que umaV
ou outra).P
).Como o número natural 0 não pode ser diminuído, a chamada
P
de um semáforo contendo um 0 bloqueará a execução do processo de chamada (/ thread) até algum momento em que o número não seja mais 0 eP
possa ser executado com êxito (e atomicamente).Conforme mencionado em outras respostas, os semáforos podem ser usados para restringir o acesso a um determinado recurso a um número máximo (mas variável) de processos.
fonte
Eu criei a visualização que deve ajudar a entender a ideia. O semáforo controla o acesso a um recurso comum em um ambiente multithreading.
Resultado
Código de exemplo do artigo
fonte
Um sinalizador de hardware ou software. Em sistemas multitarefa, um semáforo é uma variável com um valor que indica o status de um recurso comum. Um processo que precisa do recurso verifica o semáforo para determinar o status dos recursos e decide como proceder.
fonte
Os semáforos agem como limitadores de rosca.
Exemplo: se você possui um pool de 100 threads e deseja executar alguma operação de banco de dados. Se 100 threads acessarem o banco de dados em um determinado momento, pode haver um problema de bloqueio no banco de dados, para que possamos usar o semáforo que permite apenas threads limitados por vez. O exemplo abaixo permite apenas um thread por vez. Quando um thread chama o
acquire()
método, ele obtém o acesso e, após chamar orelease()
método, libera o acesso para que o próximo thread obtenha o acesso.fonte
Imagine que todo mundo está tentando ir ao banheiro e há apenas um certo número de chaves no banheiro. Agora, se não houver chaves suficientes, essa pessoa precisa esperar. Então, pense no semáforo como representando o conjunto de chaves disponíveis para banheiros (os recursos do sistema) aos quais diferentes processos (frequentadores de banheiros) podem solicitar acesso.
Agora imagine dois processos tentando ir ao banheiro ao mesmo tempo. Essa não é uma boa situação e semáforos são usados para evitar isso. Infelizmente, o semáforo é um mecanismo voluntário e os processos (nossos frequentadores do banheiro) podem ignorá-lo (ou seja, mesmo que haja chaves, alguém ainda pode simplesmente abrir a porta).
Também existem diferenças entre os semáforos binários / mutex e de contagem.
Confira as notas da aula em http://www.cs.columbia.edu/~jae/4118/lect/L05-ipc.html .
fonte
Esta é uma pergunta antiga, mas um dos usos mais interessantes do semáforo é um bloqueio de leitura / gravação e não foi mencionado explicitamente.
Os bloqueios r / w funcionam de maneira simples: consuma uma permissão para um leitor e todas as permissões para escritores. De fato, uma implementação trivial de ar / w lock, mas requer modificação de metadados na leitura (na verdade duas vezes) que pode se tornar um gargalo, ainda significativamente melhor do que um mutex ou bloqueio.
Outra desvantagem é que os escritores também podem ser iniciados com bastante facilidade, a menos que o semáforo seja justo ou que as gravações obtenham permissões em várias solicitações; nesse caso, eles precisam de um mutex explícito entre si.
Leia mais :
fonte
Um semáforo é uma maneira de bloquear um recurso para garantir que, enquanto um pedaço de código é executado, apenas esse pedaço de código tenha acesso a esse recurso. Isso evita que dois threads acessem simultaneamente um recurso, o que pode causar problemas.
fonte