Existe alguma diferença entre um semáforo binário e um mutex ou eles são essencialmente iguais?
Existe alguma diferença entre um semáforo binário e um mutex ou eles são essencialmente iguais?
Respostas:
Eles não são a mesma coisa. Eles são usados para diferentes propósitos!
Embora os dois tipos de semáforos tenham um estado cheio / vazio e usem a mesma API, seu uso é muito diferente.
Semáforos
de exclusão mútua Os semáforos de exclusão mútua são usados para proteger recursos compartilhados (estrutura de dados, arquivo, etc.).
Um semáforo Mutex é "pertencente" à tarefa que o executa. Se a Tarefa B tentar fornecer um mutex atualmente retido pela Tarefa A, a chamada da Tarefa B retornará um erro e falhará.
Os mutexes sempre usam a seguinte sequência:
- SemTake - Seção Crítica - SemGive
Aqui está um exemplo simples:
Linha A Linha B Tome Mutex acessar dados ... Tome Mutex <== Bloqueará ... Forneça dados de acesso ao Mutex <== Desbloqueia ... Give Mutex
Semáforo
binário O semáforo binário aborda uma questão totalmente diferente:
Task A Task B
... Take BinSemaphore <== wait for something
Do Something Noteworthy
Give BinSemaphore do something <== unblocks
Observe que, com um semáforo binário, não há problema em B pegar o semáforo e A para fornecê-lo.
Novamente, um semáforo binário NÃO está protegendo um recurso do acesso. O ato de dar e receber um semáforo é fundamentalmente dissociado.
Normalmente, faz pouco sentido para a mesma tarefa dar um dar e receber um mesmo semáforo binário.
portanto, os semáforos são mais adequados para alguns problemas de sincronização, como produtor-consumidor.
No Windows, os semáforos binários são mais como objetos de eventos do que mutexes.
Mutex can be released only by thread that had acquired it
- Eu apenas tentei com um programa baseado simples pthread_mutex, um thread pode desbloquear mutex bloqueado no segmento principal
O exemplo do WC é uma analogia agradável:
Mutex:
É a chave para um banheiro. Uma pessoa pode ter a chave - ocupar o banheiro - no momento. Quando termina, a pessoa fornece (libera) a chave para a próxima pessoa na fila.
Oficialmente: "Os mutexes geralmente são usados para serializar o acesso a uma seção do código reentrante que não pode ser executada simultaneamente por mais de um thread. Um objeto mutex permite apenas um thread em uma seção controlada, forçando outros threads que tentam obter acesso a nessa seção para aguardar até que o primeiro thread saia dessa seção ". Ref: Biblioteca do desenvolvedor Symbian
(Um mutex é realmente um semáforo com o valor 1.)
Semáforo:
É o número de chaves de banheiro idênticas gratuitas. Por exemplo, digamos que temos quatro banheiros com fechaduras e chaves idênticas. A contagem de semáforos - a contagem de chaves - é definida como 4 no início (todos os quatro banheiros são gratuitos), então o valor da contagem é diminuído à medida que as pessoas entram. Se todos os banheiros estiverem cheios, por exemplo. não há chaves livres restantes, a contagem de semáforos é 0. Agora, quando eq. uma pessoa sai do banheiro, o semáforo é aumentado para 1 (uma chave livre) e entregue à próxima pessoa na fila.
Oficialmente: "Um semáforo restringe o número de usuários simultâneos de um recurso compartilhado até um número máximo. Os encadeamentos podem solicitar acesso ao recurso (diminuindo o semáforo) e podem sinalizar que eles terminaram de usar o recurso (incrementando o semáforo). " Ref: Biblioteca do desenvolvedor Symbian
Bons artigos sobre o tema:
Da parte 2:
O mutex é semelhante aos princípios do semáforo binário com uma diferença significativa: o princípio da propriedade. Propriedade é o conceito simples de que, quando uma tarefa trava (adquire) um mutex, somente ele pode desbloqueá-lo (liberá-lo). Se uma tarefa tentar desbloquear um mutex, ele não foi bloqueado (portanto, não possui), uma condição de erro será encontrada e, mais importante, o mutex não será desbloqueado. Se o objeto de exclusão mútua não possui propriedade, irrelevante o que é chamado, não é um mutex.
Como nenhuma das respostas acima elimina a confusão, aqui está uma que esclareceu minha confusão.
A rigor, um mutex é um mecanismo de bloqueio usado para sincronizar o acesso a um recurso. Somente uma tarefa (pode ser um encadeamento ou processo baseado na abstração do SO) pode adquirir o mutex. Isso significa que haverá propriedade associada ao mutex e apenas o proprietário poderá liberar o bloqueio (mutex).
O semáforo é um mecanismo de sinalização (tipo de sinal "Estou pronto, você pode continuar"). Por exemplo, se você estiver ouvindo músicas (assuma isso como uma tarefa) no seu celular e ao mesmo tempo que seu amigo ligou para você, uma interrupção será acionada, na qual uma rotina de serviço de interrupção (ISR) sinalizará a tarefa de processamento de chamadas para ativar .
Sua semântica de sincronização é muito diferente:
Como tal, pode-se ver um mutex como um token transmitido de tarefa para tarefa e um semáforo como sinal vermelho de trânsito ( indica a alguém que pode prosseguir).
No nível teórico, eles não são diferentes semanticamente. Você pode implementar um mutex usando semáforos ou vice-versa (veja aqui um exemplo). Na prática, a implementação é diferente e eles oferecem serviços ligeiramente diferentes.
A diferença prática (em termos de serviços do sistema que os cerca) é que a implementação de um mutex visa ser um mecanismo de sincronização mais leve. No oráculo, os mutexes são conhecidos como trincos e os semáforos são conhecidos como esperas .
No nível mais baixo, eles usam algum tipo de teste atômico e mecanismo definido . Isso lê o valor atual de um local de memória, calcula algum tipo de condicional e grava um valor nesse local em uma única instrução que não pode ser interrompida . Isso significa que você pode adquirir um mutex e testar para ver se mais alguém o teve antes de você.
Uma implementação típica do mutex possui um processo ou thread executando a instrução test-and-set e avaliando se alguma outra coisa configurou o mutex. Um ponto importante aqui é que não há interação com o agendador , portanto, não temos idéia (e não nos importamos) de quem definiu o bloqueio. Em seguida, desistimos da nossa fatia de tempo e tentamos novamente quando a tarefa é reprogramada ou executamos um bloqueio de rotação . Um bloqueio de rotação é um algoritmo como:
Count down from 5000:
i. Execute the test-and-set instruction
ii. If the mutex is clear, we have acquired it in the previous instruction
so we can exit the loop
iii. When we get to zero, give up our time slice.
Quando terminamos de executar nosso código protegido (conhecido como seção crítica ), apenas definimos o valor mutex como zero ou o que significa 'claro'. Se várias tarefas estiverem tentando adquirir o mutex, a próxima tarefa agendada após o lançamento do mutex terá acesso ao recurso. Normalmente, você usaria mutexes para controlar um recurso sincronizado no qual o acesso exclusivo é necessário apenas por períodos muito curtos, normalmente para fazer uma atualização em uma estrutura de dados compartilhada.
Um semáforo é uma estrutura de dados sincronizada (normalmente usando um mutex) que possui uma contagem e alguns wrappers de chamada do sistema que interagem com o planejador com um pouco mais de profundidade do que as bibliotecas mutex. Os semáforos são incrementados e decrementados e usados para bloquear tarefas até que outra coisa esteja pronta. Consulte Problema do produtor / consumidor para obter um exemplo simples disso. Os semáforos são inicializados com algum valor - um semáforo binário é apenas um caso especial em que o semáforo é inicializado como 1. A postagem em um semáforo tem o efeito de ativar um processo de espera.
Um algoritmo básico de semáforo se parece com:
(somewhere in the program startup)
Initialise the semaphore to its start-up value.
Acquiring a semaphore
i. (synchronised) Attempt to decrement the semaphore value
ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.
Posting a semaphore
i. (synchronised) Increment the semaphore value
ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.
iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.
No caso de um semáforo binário, a principal diferença prática entre os dois é a natureza dos serviços do sistema em torno da estrutura de dados real.
EDIT: Como evan apontou com razão, os spinlocks desaceleram uma máquina de processador único. Você usaria apenas um spinlock em uma caixa com vários processadores, porque em um único processador o processo que contém o mutex nunca o redefinirá enquanto outra tarefa estiver em execução. Spinlocks são úteis apenas em arquiteturas com vários processadores.
futex
chamada do sistema Linux existe para ajudar as implementações de mutex / semáforo de espaço de usuário de baixa latência. en.wikipedia.org/wiki/Futex ) No caminho rápido sem contenção, ou se o recurso for disponibilizado em breve, você nunca terá a sobrecarga de uma chamada do sistema. Mas você não gasta mais do que alguns microssegundos ocupados em espera (girando). O ajuste dos parâmetros de retorno e espera do loop de rotação depende do hardware e da carga de trabalho, é claro, mas a biblioteca padrão geralmente tem opções razoáveis.
Embora mutex e semáforos sejam usados como primitivos de sincronização, há uma grande diferença entre eles. No caso do mutex, apenas o encadeamento que bloqueou ou adquiriu o mutex pode desbloqueá-lo. No caso de um semáforo, um encadeamento aguardando um semáforo pode ser sinalizado por um encadeamento diferente. Alguns sistemas operacionais suportam o uso de mutex e semáforos entre processos. Normalmente, o uso é criado na memória compartilhada.
Mutex: Suponha que o segmento de seção crítica T1 queira acessá-lo e siga as etapas abaixo. T1:
Semáforo binário: funciona com base em sinalização de espera e sinal. espera (s) diminui o valor "s" em um geralmente o valor "s" é inicializado com o valor "1", sinal (es) aumenta o valor "s" em um. se o valor "s" for 1 significa que ninguém está usando a seção crítica, quando valor for 0 significa que a seção crítica está em uso. suponha que o segmento T2 esteja usando a seção crítica e siga as etapas abaixo. T2:
A principal diferença entre o mutex e o semáforo binário está no Mutext se o thread bloquear a seção crítica, então ele tem que desbloquear a seção crítica, nenhum outro thread pode desbloqueá-lo, mas no caso do semáforo binário, se um thread bloqueia a seção crítica usando a função wait (s) e, em seguida, valor de s se torna "0" e ninguém pode acessá-lo até que o valor de "s" se torne 1, mas suponha que alguns outros chamados de thread sinalizem que o valor de "s" se torne 1 e permite que outra função use a seção crítica. portanto, no segmento de semáforo binário não tem propriedade.
No Windows, existem duas diferenças entre mutexes e semáforos binários:
Um mutex só pode ser liberado pelo encadeamento que possui propriedade, ou seja, o encadeamento que anteriormente chamava a função Wait (ou que assumiu a propriedade ao criá-lo). Um semáforo pode ser liberado por qualquer thread.
Um encadeamento pode chamar uma função de espera repetidamente em um mutex sem bloquear. No entanto, se você chamar uma função de espera duas vezes em um semáforo binário sem liberar o semáforo no meio, o encadeamento será bloqueado.
Obviamente, você usa o mutex para bloquear dados em um thread acessado por outro thread ao mesmo tempo. Suponha que você acabou de ligar lock()
e no processo de acesso aos dados. Isso significa que você não espera que nenhum outro thread (ou outra instância do mesmo código de thread) acesse os mesmos dados bloqueados pelo mesmo mutex. Ou seja, se é o mesmo código de thread sendo executado em uma instância de thread diferente, bate no bloqueio, então olock()
deve bloquear o fluxo de controle lá. Isso se aplica a um encadeamento que usa um código de encadeamento diferente, que também acessa os mesmos dados e também é bloqueado pelo mesmo mutex. Nesse caso, você ainda está acessando os dados e poderá levar, digamos, mais 15 segundos para alcançar o desbloqueio do mutex (para que o outro encadeamento bloqueado no bloqueio do mutex seja desbloqueado e permita que o controle acessar os dados). Você, a qualquer custo, permite que outro encadeamento desbloqueie o mesmo mutex e, por sua vez, permita que o encadeamento que já está aguardando (bloqueando) no bloqueio do mutex desbloqueie e acesse os dados? Espero que você entenda o que estou dizendo aqui? Conforme definido na definição universal !,
Portanto, se você é muito específico sobre o uso de semáforo binário em vez de mutex, deve ter muito cuidado em "definir o escopo" dos bloqueios e desbloqueios. Quero dizer que todo fluxo de controle que atinge cada bloqueio deve atingir uma chamada de desbloqueio, também não deve haver nenhum “primeiro desbloqueio”, mas sempre deve ser “primeiro bloqueio”.
Mutex são usados para "Mecanismos de Bloqueio". um processo de cada vez pode usar um recurso compartilhado
enquanto que
Os semáforos são usados para "Mecanismos de sinalização" como "Estou pronto, agora posso continuar"
Mito:
Alguns artigos dizem que "o semáforo binário e o mutex são iguais" ou "o semáforo com o valor 1 é mutex", mas a diferença básica é que o Mutex pode ser liberado apenas pelo segmento que o adquiriu, enquanto você pode sinalizar o semáforo de qualquer outro segmento
Pontos chave:
• Um encadeamento pode adquirir mais de um bloqueio (Mutex).
• Um mutex pode ser bloqueado mais de uma vez apenas se for um mutex recursivo; aqui, bloquear e desbloquear para mutex deve ser o mesmo
• Se um encadeamento que já havia bloqueado um mutex, tentar bloqueá-lo novamente, ele entrará na lista de espera desse mutex, o que resultará em um impasse.
• O semáforo binário e o mutex são semelhantes, mas não iguais.
• O Mutex é uma operação cara devido aos protocolos de proteção associados a ele.
• O objetivo principal do mutex é obter acesso atômico ou bloquear recursos
Um Mutex controla o acesso a um único recurso compartilhado. Ele fornece operações para adquirir () acesso a esse recurso e liberá- lo () quando concluído.
Um semáforo controla o acesso a um conjunto compartilhado de recursos. Ele fornece operações para Wait () até que um dos recursos do pool fique disponível e Signal () quando ele é devolvido ao pool.
Quando o número de recursos que um semáforo protege é maior que 1, é chamado de semáforo de contagem . Quando ele controla um recurso, é chamado de Semáforo Booleano . Um semáforo booleano é equivalente a um mutex.
Assim, um semáforo é uma abstração de nível mais alto que o Mutex. Um Mutex pode ser implementado usando um semáforo, mas não o contrário.
A pergunta modificada é - Qual é a diferença entre um mutex e um semáforo "binário" no "Linux"?
Resp: A seguir estão as diferenças - i) Escopo - O escopo do mutex está dentro de um espaço de endereço do processo que o criou e é usado para sincronização de encadeamentos. Enquanto o semáforo pode ser usado no espaço do processo e, portanto, pode ser usado para sincronização entre processos.
ii) O Mutex é leve e mais rápido que o semáforo. Futex é ainda mais rápido.
iii) O Mutex pode ser adquirido pelo mesmo encadeamento com êxito várias vezes, com a condição de liberá-lo o mesmo número de vezes. Outro segmento que tentar adquirir será bloqueado. Enquanto no caso do semáforo, se o mesmo processo tentar adquiri-lo novamente, ele bloqueia, pois pode ser adquirido apenas uma vez.
Diferença entre o semáforo binário e o Mutex: PROPRIEDADE: os semáforos podem ser sinalizados (publicados) mesmo de um proprietário não atual. Isso significa que você pode simplesmente postar a partir de qualquer outro tópico, embora você não seja o proprietário.
O semáforo é uma propriedade pública em processo, pode ser simplesmente postada por um thread não proprietário. Por favor, marque essa diferença nas letras BOLD, significa muito.
O trabalho da Mutex sobre o bloqueio da região crítica, mas o Semaphore trabalha em contagem.
http://www.geeksforgeeks.org/archives/9102 discute em detalhes.
Mutex
é um mecanismo de bloqueio usado para sincronizar o acesso a um recurso.
Semaphore
é um mecanismo de sinalização.
Cabe ao programador se ele / ela deseja usar o semáforo binário no lugar do mutex.
Além do fato de os mutexes terem um proprietário, os dois objetos podem ser otimizados para uso diferente. Os mutexes são projetados para serem mantidos apenas por um curto período de tempo; violar isso pode causar desempenho ruim e agendamento injusto. Por exemplo, um segmento em execução pode ter permissão para adquirir um mutex, mesmo que outro segmento já esteja bloqueado nele. Os semáforos podem fornecer mais justiça, ou a justiça pode ser forçada usando várias variáveis de condição.
sem_post()
para SCHED_FIFO
e SCHED_RR
(ambos estes não são padrão): o maior thread de prioridade, e se houver múltiplos com a mesma prioridade, o segmento que tem sido esperando por mais tempo. O OpenSolaris segue essa regra FIFO até certo ponto, mesmo para agendamento normal. Para o glibc e o FreeBSD, desbloquear um mutex simples (por exemplo, sem proteção de prioridade ou herança de prioridade) e postar um semáforo são basicamente os mesmos, marcando o objeto como desbloqueado e, se houver threads em espera, chamando o kernel para ativar um.
No Windows, a diferença é a seguinte. MUTEX: o processo que executa com êxito a espera deve executar um sinal e vice-versa. SEMÁFORES BINÁRIOS: Diferentes processos podem executar operações de espera ou sinalização em um semáforo.
Embora um semáforo binário possa ser usado como um mutex, um mutex é um caso de uso mais específico, pois apenas o processo que bloqueou o mutex deve desbloqueá-lo. Essa restrição de propriedade torna possível fornecer proteção contra:
Essas restrições nem sempre estão presentes porque degradam a velocidade. Durante o desenvolvimento do seu código, você pode ativar essas verificações temporariamente.
por exemplo, você pode ativar o atributo de verificação de erro no seu mutex. O erro ao verificar os mutexes retorna EDEADLK
se você tentar bloquear o mesmo duas vezes e EPERM
se desbloquear um mutex que não seja seu.
pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);
Depois de inicializados, podemos colocar essas verificações em nosso código da seguinte maneira:
if(pthread_mutex_unlock(&mutex)==EPERM)
printf("Unlock failed:Mutex not owned by this thread\n");
O conceito ficou claro para mim depois de passar por cima das postagens. Mas havia algumas perguntas remanescentes. Então, eu escrevi este pequeno pedaço de código.
Quando tentamos dar um semáforo sem pegá-lo, ele passa. Mas, quando você tenta dar um mutex sem tomá-lo, ele falha. Eu testei isso em uma plataforma Windows. Habilite USE_MUTEX para executar o mesmo código usando um MUTEX.
#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1
DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );
HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;
int main(void)
{
#ifdef USE_MUTEX
ghMutex = CreateMutex( NULL, FALSE, NULL);
if (ghMutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
#else
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
#endif
// Create thread 1.
Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);
if ( Handle_Of_Thread_1 == NULL)
{
printf("Create first thread problem \n");
return 1;
}
/* sleep for 5 seconds **/
Sleep(5 * 1000);
/*Create thread 2 */
Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);
if ( Handle_Of_Thread_2 == NULL)
{
printf("Create second thread problem \n");
return 1;
}
// Sleep for 20 seconds
Sleep(20 * 1000);
printf("Out of the program \n");
return 0;
}
int my_critical_section_code(HANDLE thread_handle)
{
#ifdef USE_MUTEX
if(thread_handle == Handle_Of_Thread_1)
{
/* get the lock */
WaitForSingleObject(ghMutex, INFINITE);
printf("Thread 1 holding the mutex \n");
}
#else
/* get the semaphore */
if(thread_handle == Handle_Of_Thread_1)
{
WaitForSingleObject(ghSemaphore, INFINITE);
printf("Thread 1 holding semaphore \n");
}
#endif
if(thread_handle == Handle_Of_Thread_1)
{
/* sleep for 10 seconds */
Sleep(10 * 1000);
#ifdef USE_MUTEX
printf("Thread 1 about to release mutex \n");
#else
printf("Thread 1 about to release semaphore \n");
#endif
}
else
{
/* sleep for 3 secconds */
Sleep(3 * 1000);
}
#ifdef USE_MUTEX
/* release the lock*/
if(!ReleaseMutex(ghMutex))
{
printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
}
#else
if (!ReleaseSemaphore(ghSemaphore,1,NULL) )
{
printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
}
#endif
return 0;
}
DWORD WINAPI Thread_no_1( LPVOID lpParam )
{
my_critical_section_code(Handle_Of_Thread_1);
return 0;
}
DWORD WINAPI Thread_no_2( LPVOID lpParam )
{
my_critical_section_code(Handle_Of_Thread_2);
return 0;
}
O simples fato de o semáforo permitir sinalizar "é feito usando um recurso", mesmo que nunca tenha sido o proprietário, me faz pensar que há um acoplamento muito frouxo entre possuir e sinalizar no caso de semáforos.
O Mutex é usado para proteger o código e os dados confidenciais, o semáforo é usado para a sincronização. Você também pode ter um uso prático com a proteção do código confidencial, mas pode haver um risco de liberar a proteção pelo outro encadeamento pela operação V. A diferença entre bi-semáforo e mutex é a propriedade. Por exemplo, no banheiro, o Mutex é como alguém que pode entrar no banheiro e trancar a porta, ninguém mais pode entrar até que o homem saia, o bi-semáforo é como aquele que pode entrar o banheiro e trancar a porta, mas alguém poderia entrar pedindo ao administrador para abrir a porta, é ridículo.
Mutex
Os mutexes geralmente são usados para serializar o acesso a uma seção do código reentrante que não pode ser executada simultaneamente por mais de um thread. Um objeto mutex permite apenas um encadeamento em uma seção controlada, forçando outros encadeamentos que tentam obter acesso a essa seção a aguardar até que o primeiro encadeamento saia dessa seção.O uso inadequado de um mutex é proteger um recurso compartilhado. efeito colateral não intencional. Quaisquer duas tarefas do RTOS que operam com prioridades diferentes e coordenadas por meio de um mutex criam a oportunidade de inversão de prioridade . O Mutex trabalha no espaço do usuário .
Semáforo
O semáforo é um mecanismo de sinalização. O semáforo restringe o número de usuários simultâneos de um recurso compartilhado até um número máximo. Os encadeamentos podem solicitar acesso ao recurso (decrementando o semáforo) e podem sinalizar que eles terminaram de usar o recurso (incrementando o semáforo). Ele permite que o número de threads acesse recursos compartilhados. O uso correto de um semáforo é para sinalizar de uma tarefa para outra. Os semáforos também podem ser usados para sinalizar de uma rotina de serviço de interrupção (ISR) para uma tarefa. A sinalização de um semáforo é um comportamento RTOS sem bloqueio e, portanto, seguro para ISR. Como essa técnica elimina a necessidade propensa a erros de desativar interrupções no nível da tarefa. Isso funciona no espaço do kernel .
A resposta pode depender do sistema operacional de destino. Por exemplo, pelo menos uma implementação RTOS com a qual estou familiarizado permitirá várias operações sequenciais de "obtenção" em um único mutex do SO, desde que todas elas estejam no mesmo contexto de encadeamento. Os múltiplo get devem ser substituídos por um número igual de put antes que outro thread possa obter o mutex. Isso difere dos semáforos binários, para os quais apenas uma única obtenção é permitida por vez, independentemente dos contextos de encadeamento.
A idéia por trás desse tipo de mutex é que você protege um objeto, permitindo apenas que um único contexto modifique os dados por vez. Mesmo que o thread obtenha o mutex e, em seguida, chame uma função que modifique ainda mais o objeto (e obtenha / coloque o mutex protetor em torno de suas próprias operações), as operações ainda deverão ser seguras, porque todas elas estão acontecendo em um único thread.
{
mutexGet(); // Other threads can no longer get the mutex.
// Make changes to the protected object.
// ...
objectModify(); // Also gets/puts the mutex. Only allowed from this thread context.
// Make more changes to the protected object.
// ...
mutexPut(); // Finally allows other threads to get the mutex.
}
Obviamente, ao usar esse recurso, você deve ter certeza de que todos os acessos em um único thread são realmente seguros!
Não tenho certeza de quão comum é essa abordagem ou se ela se aplica fora dos sistemas com os quais estou familiarizado. Para um exemplo desse tipo de mutex, consulte o ThreadX RTOS.
Os mutexes têm propriedade, diferentemente dos semáforos. Embora qualquer encadeamento, dentro do escopo de um mutex, possa obter um mutex desbloqueado e bloquear o acesso à mesma seção crítica do código, apenas o encadeamento que bloqueou um mutex deve desbloqueá-lo .
Como muitas pessoas mencionaram aqui, um mutex é usado para proteger um trecho de código crítico (seção crítica AKA). Você irá adquirir o mutex (bloqueio), entrar na seção crítica e liberar o mutex (desbloqueio) no mesmo encadeamento .
Ao usar um semáforo, você pode fazer um thread aguardar em um semáforo (por exemplo, segmento A), até que outro segmento (por exemplo, segmento B) conclua qualquer tarefa e, em seguida, defina o Semáforo para o segmento A para interromper a espera e continuar sua tarefa.
Melhor solução
A única diferença é
1.Mutex -> lock e unlock estão sob a propriedade de um segmento que bloqueia o mutex.
2.Semaphore -> Sem propriedade, ou seja; se um thread chamar semwait (s), qualquer outro thread poderá chamar sempost (s) para remover a trava.
MUTEX
Até recentemente, o único bloqueio para dormir no kernel era o semáforo. A maioria dos usuários de semáforos instanciava um semáforo com uma contagem de um e os tratava como uma trava de exclusão mútua - uma versão adormecida da trava giratória. Infelizmente, os semáforos são bastante genéricos e não impõem restrições de uso. Isso os torna úteis para gerenciar o acesso exclusivo em situações obscuras, como danças complicadas entre o kernel e o espaço do usuário. Mas isso também significa que o bloqueio mais simples é mais difícil de fazer, e a falta de regras aplicadas torna impossível qualquer tipo de depuração automatizada ou aplicação de restrições. Buscando um bloqueio simples para dormir, os desenvolvedores do kernel introduziram o mutex. Sim, como você já está acostumado, esse é um nome confuso. Vamos esclarecer. O termo "mutex" é um nome genérico para se referir a qualquer cadeado que imponha exclusão mútua, como um semáforo com uma contagem de uso de um. Nos kernels recentes do Linux, o nome próprio "mutex" agora também é um tipo específico de bloqueio de suspensão que implementa exclusão mútua. Ou seja, um mutex é um mutex.
A simplicidade e eficiência do mutex vêm das restrições adicionais impostas a seus usuários além do que o semáforo exige. Diferentemente de um semáforo, que implementa o comportamento mais básico de acordo com o design original de Dijkstra, o mutex possui um caso de uso mais restrito e restrito: n Somente uma tarefa pode reter o mutex por vez. Ou seja, a contagem de uso em um mutex é sempre uma.
[1] Desenvolvimento de Kernel Linux, Terceira Edição Robert Love
Acho que a maioria das respostas aqui foram confusas, especialmente aquelas que dizem que o mutex pode ser liberado apenas pelo processo que o contém, mas o semáforo pode ser sinalizado por qualquer processo. A linha acima é meio vaga em termos de semáforo. Para entender, devemos saber que existem dois tipos de semáforo: um é chamado semáforo de contagem e o outro é chamado de semáforo binário. Na contagem, o semáforo lida com o acesso a n número de recursos em que n pode ser definido antes do uso. Cada semáforo possui uma variável de contagem, que mantém a contagem do número de recursos em uso, inicialmente, é definido como n. Cada processo que deseja usar um recurso executa uma operação wait () no semáforo (diminuindo a contagem). Quando um processo libera um recurso, ele executa uma operação release () (incrementando a contagem). Quando a contagem se torna 0, todos os recursos estão sendo usados. Depois disso, o processo aguarda até que a contagem se torne maior que 0. Agora, aqui está o problema: apenas o processo que contém o recurso pode aumentar a contagem; nenhum outro processo pode aumentar a contagem; apenas os processos que mantêm um recurso podem aumentar a contagem e o processo. esperar pelo semáforo novamente e, quando vê o recurso disponível, diminui a contagem novamente. Portanto, em termos de semáforo binário, apenas o processo que contém o semáforo pode aumentar a contagem, e a contagem permanece zero até que ele pare de usar o semáforo e aumente a contagem e outro processo tenha a chance de acessar o semáforo. Agora, aqui está o problema: apenas o processo que retém o recurso pode aumentar a contagem; nenhum outro processo pode aumentar a contagem; apenas os processos que mantêm um recurso podem aumentar a contagem e o processo aguardando o semáforo verifica novamente e, quando vê o recurso disponível, diminui a contagem novamente. Portanto, em termos de semáforo binário, apenas o processo que contém o semáforo pode aumentar a contagem, e a contagem permanece zero até que ele pare de usar o semáforo e aumente a contagem e outro processo tenha a chance de acessar o semáforo. Agora, aqui está o problema: apenas o processo que retém o recurso pode aumentar a contagem; nenhum outro processo pode aumentar a contagem; apenas os processos que mantêm um recurso podem aumentar a contagem e o processo aguardando o semáforo verifica novamente e, quando vê o recurso disponível, diminui a contagem novamente. Portanto, em termos de semáforo binário, apenas o processo que contém o semáforo pode aumentar a contagem, e a contagem permanece zero até que ele pare de usar o semáforo e aumente a contagem e outro processo tenha a chance de acessar o semáforo.
A principal diferença entre o semáforo binário e o mutex é que o semáforo é um mecanismo de sinalização e o mutex é um mecanismo de bloqueio, mas o semáforo binário parece funcionar como o mutex que cria confusão, mas ambos são conceitos diferentes, adequados para diferentes tipos de trabalho.