O que é mutex e semáforo em Java? Qual é a principal diferença?

Respostas:

115

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" .

Eric
fonte
4
Isso não é bem verdade. A mesma thread pode entrar no mesmo mutex mais de uma vez, então uma contagem precisa ser mantida para garantir que as entradas e saídas sejam balanceadas.
finnw
1
@finnw, em geral existem dois tipos de mutexes, recursivos e não recursivos. O Java, por padrão, usa o tipo recursivo?
edA-qa mort-ora-y
2
@ edA-qa mort-ora-y, o termo "Mutex" não é usado na Java VM ou nas especificações da API, então estou assumindo que se refere ao monitor embutido em cada objeto, que também é semelhante ao objeto Win32 chamado Mutex . O mesmo se aplica a a 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.
finnw
2
Mutexes não recursivos podem ser implementados usando um Semaphore com contagem um. Isso pode ser útil se você quiser evitar chamadas recursivas. Isso tem usos práticos, eu pessoalmente usei em grandes projetos para detectar loops no código de inicialização (A inicializa B, que tenta inicializar A novamente).
Alexander Torstling
1
No padrão C ++ 11 (C ++ 0x), mutex não é recursivo. Eles também fornecem um 'recursive_mutex' separado para aqueles que precisam disso. Eu sei que estamos falando de Java aqui, mas muitos de nós codificam em várias linguagens agora.
Aditya Kumar Pandey
139

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.

Feabhas
fonte
1
A resposta de Feabhas é muito importante - o mutex verifica se o thread que tenta liberar o mutex realmente o possui. Eu fiz isso como uma pergunta de entrevista, então vale a pena tentar se lembrar dela.
andrew pate
40

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?

  • Mutex - seu ONE.
  • Semáforo - é DEFINED_COUNT, (tanto quanto a contagem do semáforo)
aJ.
fonte
8

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.

Jason Coco
fonte
3

Um semáforo é um mecanismo de sincronização de contagem, um mutex não.

Brian Rasmussen
fonte
3

Um mutex é geralmente conhecido como semáforo binário. Embora um semáforo possa ser criado com qualquer contagem diferente de zero, um mutex é conceitualmente um semáforo com uma contagem superior de 1.

Sean
fonte
1

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. Cada release()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:

  1. 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.

  2. 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.

  3. 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.

Ravindra babu
fonte
0

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.

dim8
fonte
0

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.

Amarildo
fonte
0

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.

Marwen Trabelsi
fonte