Respostas:
O semáforo pode ser contado, enquanto o mutex só pode contar até 1.
Suponha que você tenha um thread em execução que aceite conexões de cliente. Este thread pode lidar com 10 clientes simultaneamente. Então, cada novo cliente configura o semáforo até chegar a 10. Quando o Semaphore tiver 10 sinalizadores, então sua thread não aceitará novas conexões
Mutex geralmente é usado para guardar coisas. Suponha que seus 10 clientes possam acessar várias partes do sistema. Então, você pode proteger uma parte do sistema com um mutex para que, quando 1 cliente estiver conectado a esse subsistema, ninguém mais tenha acesso. Você também pode usar um semáforo para essa finalidade. Um mutex é um "Semáforo de exclusão mútua" .
ReentrantLock
. Todos esses são recursivos. Não tenho conhecimento de nenhum exemplo do "mundo real" de mutexes não recursivos (só os vi em livros didáticos), então não os considerei.
Infelizmente, todos não perceberam a diferença mais importante entre o semáforo e o mutex; o conceito de " propriedade ".
Os semáforos não têm noção de propriedade, isso significa que qualquer thread pode liberar um semáforo (isso pode levar a muitos problemas por si só, mas pode ajudar na "detecção de morte"). Considerando que um mutex tem o conceito de propriedade (ou seja, você só pode liberar um mutex que adquiriu).
A propriedade é extremamente importante para a programação segura de sistemas concorrentes. Eu sempre recomendaria usar mutex em vez de um semáforo (mas há implicações de desempenho).
Mutexes também podem suportar herança de prioridade (que pode ajudar com o problema de inversão de prioridade) e recursão (eliminando um tipo de deadlock).
Também deve ser apontado que existem semáforos "binários" e semáforos "de contagem / geral". O semáforo de Java é um semáforo de contagem e, portanto, permite que seja inicializado com um valor maior que um (enquanto, como apontado, um mutex pode apenas uma contagem conceitual de um). A utilidade disso foi apontada em outros posts.
Então, para resumir, a menos que você tenha vários recursos para gerenciar, eu sempre recomendaria o mutex em vez do semáforo.
Mutex é basicamente exclusão mútua. Apenas um thread pode adquirir o recurso de uma vez. Quando um thread adquire o recurso, nenhum outro thread tem permissão para adquirir o recurso até que o thread que possui o recurso seja liberado. Todos os encadeamentos aguardando aquisição de recurso seriam bloqueados.
O semáforo é usado para controlar o número de threads em execução. Haverá um conjunto fixo de recursos. A contagem de recursos será diminuída toda vez que um thread possuir o mesmo. Quando a contagem do semáforo chega a 0, nenhum outro encadeamento pode adquirir o recurso. As threads são bloqueadas até que outras threads possuam recursos.
Resumindo, a principal diferença é quantos threads têm permissão para adquirir o recurso de uma vez?
Um mutex é usado para acesso serial a um recurso, enquanto um semáforo limita o acesso a um recurso até um número definido. Você pode pensar em um mutex como um semáforo com uma contagem de acesso de 1. Qualquer coisa que você definir para a contagem do semáforo, esses threads podem acessar o recurso antes que o recurso seja bloqueado.
Um semáforo é um mecanismo de sincronização de contagem, um mutex não.
Esta pergunta tem respostas relevantes e um link para a orientação oficial do Java: Existe um Mutex em Java?
Semáforo :
Um semáforo de contagem. Conceitualmente, um semáforo mantém um conjunto de licenças. Cada
acquire()
bloco, se necessário, até que uma licença esteja disponível, e então a leva. Cadarelease()
um adiciona uma licença, potencialmente liberando um adquirente de bloqueio. No entanto, nenhum objeto de licença real é usado; o Semaphore apenas mantém uma contagem do número disponível e age de acordo.
Os semáforos são frequentemente usados para restringir o número de threads que podem acessar algum recurso (físico ou lógico)
Java não possui API Mutex integrada. Mas pode ser implementado como semáforo binário.
Um semáforo inicializado com um, e que é usado de forma que tenha apenas no máximo uma licença disponível, pode servir como um bloqueio de exclusão mútua. Isso é mais comumente conhecido como semáforo binário, porque tem apenas dois estados: uma licença disponível ou nenhuma licença disponível.
Quando usado dessa forma, o semáforo binário tem a propriedade (ao contrário de muitas implementações de Lock), que o "bloqueio" pode ser liberado por um thread diferente do proprietário (já que os semáforos não têm noção de propriedade) . Isso pode ser útil em alguns contextos especializados, como recuperação de deadlock.
Portanto, as principais diferenças entre Semaphore e Mutex:
O semáforo restringe o número de threads para acessar um recurso por meio de permissões. Mutex permite que apenas um thread acesse o recurso.
Nenhum tópico possui Semaphore. Threads podem atualizar o número de licenças chamando acquire()
e release()
métodos. Mutexes devem ser desbloqueados apenas pelo thread que mantém o bloqueio.
Quando um mutex é usado com variáveis de condição, há um colchete implícito - é claro qual parte do programa está sendo protegida . Esse não é necessariamente o caso de um semáforo, que pode ser chamado de ponto de partida da programação simultânea - ele é poderoso, mas muito fácil de usar de uma maneira não estruturada e indeterminada.
Mutex é um semáforo binário. Deve ser inicializado com 1, para que o princípio da ordem de chegada seja atendido. Isso nos leva a outra propriedade especial de cada exclusão mútua: o único que fez para baixo , deve ser aquele que faz -se . Portanto, obtivemos exclusão mútua sobre algum recurso.
Agora você pode ver que um mutex é um caso especial de semáforo geral.
O objeto de sincronização Semaphoreimplementa um semáforo clássico. Um semáforo controla o acesso a um recurso compartilhado por um contador. Se o contador for maior que zero, o acesso é concedido; Se for zero, o acesso é negado. O contador conta as permissões que permitem o acesso ao recurso compartilhado. Então, para acessar o recurso, um thread deve receber permissão do semáforo. Em geral, para usar um semáforo, o thread que deseja acessar o recurso compartilhado tenta adquirir uma licença. Se a contagem do semáforo for maior que zero, o encadeamento adquire uma licença e a contagem do semáforo é diminuída. Caso contrário, o tópico fica bloqueado até obter permissão. Quando o thread não precisa mais acessar o recurso compartilhado, ele libera a permissão, de modo que a contagem de semáforos é aumentada. Se houver outro tópico esperando por uma licença, ele adquire uma licença naquele momento. A classe Semaphore do Java implementa esse mecanismo.
O Semaphore tem dois construtores:
Semaphore(int num)
Semaphore(int num, boolean come)
num especifica a contagem inicial da licença. Então, num especifica o número de threads que podem acessar um recurso compartilhado em um determinado momento. Se num for um, ele pode acessar o recurso um thread de cada vez. Ao definir vir como verdade, você pode garantir que os tópicos que você está esperando recebem permissão na ordem em que solicitado.
Você compara o incomparável, tecnicamente não há diferença entre um Semaphore e mutex, não faz sentido. Mutex é apenas um nome significativo como qualquer nome na lógica do seu aplicativo, significa que você inicializa um semáforo em "1", geralmente é usado para proteger um recurso ou uma variável protegida para garantir a exclusão mútua.