Y a-t-il une différence entre un sémaphore binaire et un mutex ou sont-ils essentiellement les mêmes?
Y a-t-il une différence entre un sémaphore binaire et un mutex ou sont-ils essentiellement les mêmes?
Réponses:
Ce n'est PAS la même chose. Ils sont utilisés à des fins différentes!
Bien que les deux types de sémaphores aient un état plein / vide et utilisent la même API, leur utilisation est très différente.
Sémaphores d'exclusion
mutuelle Les sémaphores d'exclusion mutuelle sont utilisés pour protéger les ressources partagées (structure de données, fichier, etc.).
Un sémaphore Mutex est "détenu" par la tâche qui le prend. Si la tâche B tente de semGive un mutex actuellement détenu par la tâche A, l'appel de la tâche B retournera une erreur et échouera.
Les mutex utilisent toujours la séquence suivante:
- SemTake - Section critique - SemGive
Voici un exemple simple:
Fil A Fil B Prenez Mutex données d'accès ... Prenez Mutex <== va bloquer ... Donner aux données d'accès Mutex <== débloque ... Donnez Mutex
Sémaphore binaire Le sémaphore
binaire aborde une question totalement différente:
Task A Task B
... Take BinSemaphore <== wait for something
Do Something Noteworthy
Give BinSemaphore do something <== unblocks
Notez qu'avec un sémaphore binaire, il est OK pour B de prendre le sémaphore et A pour le donner.
Encore une fois, un sémaphore binaire NE protège PAS une ressource de l'accès. L'acte de donner et de prendre un sémaphore est fondamentalement découplé.
Il est généralement peu logique pour la même tâche de donner et de prendre le même sémaphore binaire.
les sémaphores conviennent donc mieux à certains problèmes de synchronisation comme le producteur-consommateur.
Sous Windows, les sémaphores binaires ressemblent plus à des objets d'événement qu'à des mutex.
Mutex can be released only by thread that had acquired it
- Je viens d'essayer avec un simple programme basé sur pthread_mutex, un thread peut déverrouiller un mutex verrouillé dans le thread principal
L'exemple des toilettes est une analogie agréable:
Mutex:
Est la clé des toilettes. Une personne peut avoir la clé - occuper les toilettes - à la fois. Une fois terminé, la personne remet (libère) la clé à la personne suivante dans la file d'attente.
Officiellement: "Les mutex sont généralement utilisés pour sérialiser l'accès à une section de code rentrant qui ne peut pas être exécutée simultanément par plus d'un thread. Un objet mutex autorise uniquement un thread dans une section contrôlée, forçant d'autres threads qui tentent d'accéder à cette section pour attendre que le premier thread soit sorti de cette section. " Réf: Symbian Developer Library
(Un mutex est vraiment un sémaphore de valeur 1.)
Sémaphore:
Est le nombre de clés de toilettes identiques gratuites. Par exemple, disons que nous avons quatre toilettes avec serrures et clés identiques. Le nombre de sémaphores - le nombre de clés - est réglé à 4 au début (les quatre toilettes sont gratuites), puis la valeur de comptage est décrémentée lorsque les gens entrent. Si toutes les toilettes sont pleines, c'est-à-dire. il n'y a plus de clés libres, le nombre de sémaphores est 0. Maintenant, quand éq. une personne quitte les toilettes, le sémaphore est porté à 1 (une clé gratuite) et remis à la personne suivante dans la file d'attente.
Officiellement: "Un sémaphore limite le nombre d'utilisateurs simultanés d'une ressource partagée jusqu'à un nombre maximum. Les threads peuvent demander l'accès à la ressource (décrémenter le sémaphore) et peuvent signaler qu'ils ont fini d'utiliser la ressource (incrémenter le sémaphore). " Réf: Symbian Developer Library
Jolis articles sur le sujet:
De la partie 2:
Le mutex est similaire aux principes du sémaphore binaire avec une différence significative: le principe de propriété. La propriété est le concept simple selon lequel lorsqu'une tâche verrouille (acquiert) un mutex, elle seule peut le déverrouiller (libérer). Si une tâche essaie de déverrouiller un mutex qu'elle n'a pas verrouillé (donc ne possède pas), une condition d'erreur est rencontrée et, plus important encore, le mutex n'est pas déverrouillé. Si l'objet d'exclusion mutuelle n'a pas de propriété alors, peu importe ce qu'il est appelé, ce n'est pas un mutex.
Puisqu'aucune des réponses ci-dessus ne dissipe la confusion, voici une qui a dissipé ma confusion.
À strictement parler, un mutex est un mécanisme de verrouillage utilisé pour synchroniser l'accès à une ressource. Une seule tâche (peut être un thread ou un processus basé sur l'abstraction du système d'exploitation) peut acquérir le mutex. Cela signifie qu'il y aura propriété associée au mutex, et seul le propriétaire peut libérer le verrou (mutex).
Le sémaphore est un mécanisme de signalisation (type de signal «J'ai fini, vous pouvez continuer»). Par exemple, si vous écoutez des chansons (supposez-le comme une tâche) sur votre mobile et en même temps que votre ami vous appelle, une interruption sera déclenchée sur laquelle une routine de service d'interruption (ISR) signalera la tâche de traitement des appels à se réveiller .
Leur sémantique de synchronisation est très différente:
En tant que tel, on peut voir un mutex comme un jeton transmis de tâche en tâche et un sémaphore comme feu rouge de circulation (il signale à quelqu'un qu'il peut continuer).
Au niveau théorique, ils ne sont pas différents sémantiquement. Vous pouvez implémenter un mutex en utilisant des sémaphores ou vice versa (voir ici pour un exemple). En pratique, la mise en œuvre est différente et ils offrent des services légèrement différents.
La différence pratique (en termes de services système qui les entourent) est que la mise en œuvre d'un mutex vise à être un mécanisme de synchronisation plus léger. En langage oracle, les mutex sont appelés verrous et les sémaphores sont appelés attentes .
Au niveau le plus bas, ils utilisent une sorte de test atomique et de mécanisme de réglage . Cela lit la valeur actuelle d'un emplacement mémoire, calcule une sorte de conditionnel et écrit une valeur à cet emplacement dans une seule instruction qui ne peut pas être interrompue . Cela signifie que vous pouvez acquérir un mutex et tester pour voir si quelqu'un d'autre l'avait avant vous.
Une implémentation de mutex typique a un processus ou un thread exécutant l'instruction test-and-set et évaluant si quelque chose d'autre a défini le mutex. Un point clé ici est qu'il n'y a pas d'interaction avec l' ordonnanceur , nous n'avons donc aucune idée (et ne nous en soucions pas) qui a défini le verrou. Ensuite, nous abandonnons notre tranche de temps et la réessayons lorsque la tâche est reprogrammée ou exécutons un verrou rotatif . Un verrou tournant est un algorithme comme:
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.
Lorsque nous avons terminé d'exécuter notre code protégé (connu sous le nom de section critique ), nous mettons simplement la valeur mutex à zéro ou tout ce qui signifie «effacer». Si plusieurs tâches tentent d'acquérir le mutex, la prochaine tâche programmée après la libération du mutex aura accès à la ressource. En règle générale, vous utiliseriez des mutex pour contrôler une ressource synchronisée où l'accès exclusif n'est nécessaire que pour de très courtes périodes de temps, normalement pour effectuer une mise à jour d'une structure de données partagée.
Un sémaphore est une structure de données synchronisée (utilisant généralement un mutex) qui a un nombre et certains wrappers d'appel système qui interagissent avec le planificateur dans un peu plus de profondeur que les bibliothèques mutex. Les sémaphores sont incrémentés et décrémentés et utilisés pour bloquer les tâches jusqu'à ce que quelque chose d'autre soit prêt. Voir Problème producteur / consommateur pour un exemple simple de cela. Les sémaphores sont initialisés à une certaine valeur - un sémaphore binaire est juste un cas spécial où le sémaphore est initialisé à 1. La publication dans un sémaphore a pour effet de réveiller un processus d'attente.
Un algorithme de sémaphore de base ressemble à:
(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.
Dans le cas d'un sémaphore binaire, la principale différence pratique entre les deux est la nature des services du système entourant la structure de données réelle.
EDIT: Comme evan l'a souligné à juste titre, les verrous tournants ralentiront une machine à processeur unique. Vous utiliseriez uniquement un verrou tournant sur une boîte multiprocesseur car sur un seul processeur, le processus contenant le mutex ne le réinitialisera jamais pendant qu'une autre tâche est en cours d'exécution. Les verrous tournants ne sont utiles que sur les architectures multiprocesseurs.
futex
appel système existe pour aider à faible latence userspace mutex / sémaphores implémentations. en.wikipedia.org/wiki/Futex ) Dans le chemin rapide et sans prétention, ou si la ressource devient bientôt disponible, vous n'aurez jamais les frais généraux de un appel système. Mais vous ne passez pas plus de quelques micro-secondes à attendre (tourner). Le réglage des paramètres d'interruption et d'attente de boucle de rotation dépend du matériel et de la charge de travail, bien sûr, mais la bibliothèque standard a généralement des choix raisonnables.
Bien que les mutex et les sémaphores soient utilisés comme primitives de synchronisation, il y a une grande différence entre eux. Dans le cas d'un mutex, seul le thread qui a verrouillé ou acquis le mutex peut le déverrouiller. Dans le cas d'un sémaphore, un thread en attente sur un sémaphore peut être signalé par un thread différent. Certains systèmes d'exploitation prennent en charge l'utilisation de mutex et de sémaphores entre les processus. En règle générale, l'utilisation crée dans la mémoire partagée.
Mutex: Supposons que nous ayons le thread de section critique T1 qui souhaite y accéder, il suit les étapes ci-dessous. T1:
Sémaphore binaire: il fonctionne en fonction de la signalisation de l'attente et du signal. attente (s) diminuer la valeur "s" d'une unité habituellement la valeur "s" est initialisée avec la valeur "1", le ou les signaux augmentent la valeur "s" d'une unité. si la valeur "s" est 1 signifie que personne n'utilise la section critique, lorsque la valeur est 0 signifie que la section critique est utilisée. Supposons que le thread T2 utilise la section critique, puis il suit les étapes ci-dessous. T2:
La principale différence entre Mutex et le sémaphore binaire réside dans Mutext si le thread verrouille la section critique, il doit déverrouiller la section critique, aucun autre thread ne peut le déverrouiller, mais dans le cas du sémaphore binaire si un thread verrouille la section critique en utilisant la fonction wait (s), puis la valeur de s devient "0" et personne ne peut y accéder jusqu'à ce que la valeur de "s" devienne 1, mais supposons que d'autres signaux d'appel de fil (s) puis la valeur de "s" deviennent 1 et cela permet à une autre fonction d'utiliser la section critique. par conséquent, dans le fil de sémaphore binaire n'a pas la propriété.
Sous Windows, il existe deux différences entre les mutex et les sémaphores binaires:
Un mutex ne peut être libéré que par le thread qui en est propriétaire, c'est-à-dire le thread qui appelait précédemment la fonction Wait (ou qui en a pris possession lors de sa création). Un sémaphore peut être libéré par n'importe quel thread.
Un thread peut appeler une fonction d'attente à plusieurs reprises sur un mutex sans bloquer. Cependant, si vous appelez une fonction d'attente deux fois sur un sémaphore binaire sans libérer le sémaphore entre les deux, le thread se bloquera.
Vous utilisez évidemment mutex pour verrouiller des données dans un thread accédé en même temps par un autre thread. Supposons que vous venez d'appelerlock()
et en train d'accéder aux données. Cela signifie que vous ne vous attendez pas à ce qu'un autre thread (ou une autre instance du même code de thread) accède aux mêmes données verrouillées par le même mutex. Autrement dit, s'il s'agit du même code de thread exécuté sur une instance de thread différente, frappe le verrou, puis lelock()
devrait bloquer le flux de contrôle là-bas. Cela s'applique à un thread qui utilise un code de thread différent, qui accède également aux mêmes données et qui est également verrouillé par le même mutex. Dans ce cas, vous êtes toujours en train d'accéder aux données et vous pouvez prendre, disons, 15 secondes supplémentaires pour atteindre le déverrouillage mutex (de sorte que l'autre thread qui est bloqué dans le verrouillage mutex se débloque et permette au contrôle de accéder aux données). Autorisez-vous à tout prix un autre thread à déverrouiller le même mutex, et à son tour, permettre au thread qui attend déjà (blocage) dans le verrou mutex de débloquer et d'accéder aux données? J'espère que vous avez compris ce que je dis ici? Conformément à la définition universelle convenue !,
Donc, si vous êtes très particulier à propos de l'utilisation du sémaphore binaire au lieu du mutex, alors vous devez être très prudent dans la «délimitation» des verrous et des déverrouillages. Je veux dire que chaque flux de contrôle qui frappe chaque verrou doit frapper un appel de déverrouillage, il ne devrait pas non plus y avoir de «premier déverrouillage», mais plutôt toujours «premier verrou».
Les mutex sont utilisés pour les "mécanismes de verrouillage". un processus à la fois peut utiliser une ressource partagée
tandis que
Les sémaphores sont utilisés pour les "mécanismes de signalisation" comme "j'ai terminé, maintenant je peux continuer"
Mythe:
Un couple d'articles dit que "le sémaphore binaire et le mutex sont identiques" ou "le sémaphore avec la valeur 1 est mutex" mais la différence de base est que Mutex ne peut être libéré que par le thread qui l'a acquis, tandis que vous pouvez signaler le sémaphore à partir de n'importe quel autre thread
Points clés:
• Un thread peut acquérir plusieurs verrous (Mutex).
• Un mutex peut être verrouillé plus d'une fois seulement s'il s'agit d'un mutex récursif, ici le verrouillage et le déverrouillage du mutex doivent être identiques
• Si un thread qui avait déjà verrouillé un mutex essaie de verrouiller à nouveau le mutex, il entrera dans la liste d'attente de ce mutex, ce qui entraînera un blocage.
• Le sémaphore binaire et le mutex sont similaires mais pas identiques.
• Mutex est une opération coûteuse en raison des protocoles de protection qui lui sont associés.
• L'objectif principal du mutex est d'obtenir un accès atomique ou de verrouiller la ressource
Un Mutex contrôle l'accès à une seule ressource partagée. Il fournit des opérations pour acquérir () l' accès à cette ressource et le libérer () une fois terminé.
Un sémaphore contrôle l'accès à un pool de ressources partagé. Il fournit des opérations à Wait () jusqu'à ce qu'une des ressources du pool devienne disponible et à Signal () lorsqu'elle est rendue au pool.
Lorsque le nombre de ressources protégées par un sémaphore est supérieur à 1, il est appelé sémaphore de comptage . Lorsqu'il contrôle une ressource, il est appelé sémaphore booléen . Un sémaphore booléen est équivalent à un mutex.
Ainsi, un sémaphore est une abstraction de niveau supérieur à Mutex. Un Mutex peut être implémenté à l'aide d'un sémaphore mais pas l'inverse.
La question modifiée est - Quelle est la différence entre un mutex et un sémaphore "binaire" dans "Linux"?
Rép: Voici les différences - i) Portée - La portée de mutex se trouve dans un espace d'adressage de processus qui l'a créé et est utilisé pour la synchronisation des threads. Alors que le sémaphore peut être utilisé à travers l'espace de processus et donc il peut être utilisé pour la synchronisation interprocessus.
ii) Mutex est léger et plus rapide que le sémaphore. Futex est encore plus rapide.
iii) Mutex peut être acquis par le même thread plusieurs fois avec succès à condition qu'il le libère le même nombre de fois. Tout autre thread tentant d'acquérir se bloquera. Alors qu'en cas de sémaphore si le même processus essaie de l'acquérir à nouveau il bloque car il ne peut être acquis qu'une seule fois.
Différence entre le sémaphore binaire et Mutex: PROPRIÉTÉ: Les sémaphores peuvent être signalés (publiés) même à partir d'un propriétaire non actuel. Cela signifie que vous pouvez simplement publier à partir de n'importe quel autre fil, même si vous n'êtes pas le propriétaire.
Le sémaphore est une propriété publique en cours, il peut être simplement publié par un thread non propriétaire. Veuillez marquer cette différence en caractères gras, cela signifie beaucoup.
Mutex travaille sur le blocage des régions critiques, mais Semaphore travaille sur le compte.
http://www.geeksforgeeks.org/archives/9102 discute en détail.
Mutex
est un mécanisme de verrouillage utilisé pour synchroniser l'accès à une ressource.
Semaphore
est le mécanisme de signalisation.
C'est au programmeur s'il veut utiliser un sémaphore binaire à la place de mutex.
Outre le fait que les mutex ont un propriétaire, les deux objets peuvent être optimisés pour une utilisation différente. Les mutex sont conçus pour ne durer que peu de temps; violer cela peut entraîner des performances médiocres et une planification injuste. Par exemple, un thread en cours d'exécution peut être autorisé à acquérir un mutex, même si un autre thread est déjà bloqué dessus. Les sémaphores peuvent fournir plus d'équité, ou l'équité peut être forcée en utilisant plusieurs variables de condition.
sem_post()
pour SCHED_FIFO
et SCHED_RR
(ces deux sont pas par défaut): le fil la plus haute priorité, et s'il existe plusieurs avec la même priorité, le fil qui attend le plus longtemps. OpenSolaris suit cette règle FIFO dans une certaine mesure, même pour une planification normale. Pour glibc et FreeBSD, le déverrouillage d'un simple mutex (c'est-à-dire pas la protection prioritaire ou la priorité héritée) et la publication d'un sémaphore sont fondamentalement les mêmes, marquant l'objet comme déverrouillé et ensuite, s'il peut y avoir des threads en attente, appelant le noyau pour en réveiller un.
Sous Windows, la différence est la suivante. MUTEX: le processus qui exécute avec succès l' attente doit exécuter un signal et vice versa. SEMAPHORES BINAIRES: Différents processus peuvent exécuter une opération d' attente ou de signal sur un sémaphore.
Alors qu'un sémaphore binaire peut être utilisé comme mutex, un mutex est un cas d'utilisation plus spécifique, en ce sens que seul le processus qui a verrouillé le mutex est censé le déverrouiller. Cette contrainte de propriété permet d'assurer une protection contre:
Ces contraintes ne sont pas toujours présentes car elles dégradent la vitesse. Pendant le développement de votre code, vous pouvez activer ces contrôles temporairement.
par exemple, vous pouvez activer l'attribut de vérification d'erreur dans votre mutex. Une erreur de vérification des mutex revient EDEADLK
si vous essayez de verrouiller le même deux fois et EPERM
si vous déverrouillez un mutex qui n'est pas le vôtre.
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);
Une fois initialisés, nous pouvons placer ces contrôles dans notre code comme ceci:
if(pthread_mutex_unlock(&mutex)==EPERM)
printf("Unlock failed:Mutex not owned by this thread\n");
Le concept était clair pour moi après être allé au-dessus des messages. Mais il y avait des questions persistantes. J'ai donc écrit ce petit morceau de code.
Lorsque nous essayons de donner un sémaphore sans le prendre, cela passe. Mais, lorsque vous essayez de donner un mutex sans le prendre, il échoue. J'ai testé cela sur une plate-forme Windows. Activez USE_MUTEX pour exécuter le même code à l'aide d'un 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;
}
Le fait même que le sémaphore vous permette de signaler "c'est fait en utilisant une ressource", même s'il n'a jamais possédé la ressource, me fait penser qu'il y a un couplage très lâche entre la possession et la signalisation dans le cas des sémaphores.
Mutex est utilisé pour protéger le code et les données sensibles, le sémaphore est utilisé pour la synchronisation.Vous pouvez également avoir une utilisation pratique pour protéger le code sensible, mais il peut y avoir un risque de libération de la protection par l'autre thread par l'opération V.So La différence entre le bi-sémaphore et le mutex est la propriété.Par exemple, par les toilettes, Mutex est comme si on pouvait entrer dans les toilettes et verrouiller la porte, personne d'autre ne pouvait entrer jusqu'à ce que l'homme sorte, le bi-sémaphore est comme on peut entrer les toilettes et verrouiller la porte, mais quelqu'un d'autre pourrait entrer en demandant à l'administrateur d'ouvrir la porte, c'est ridicule.
Mutex
Les mutex sont généralement utilisés pour sérialiser l'accès à une section de code réentrant qui ne peut pas être exécutée simultanément par plus d'un thread. Un objet mutex n'autorise qu'un seul thread dans une section contrôlée, forçant les autres threads qui tentent d'accéder à cette section à attendre que le premier thread soit sorti de cette section.Une utilisation appropriée d'un mutex est de protéger une ressource partagée peut avoir un danger effet secondaire involontaire. Deux tâches RTOS qui fonctionnent à des priorités différentes et se coordonnent via un mutex, créent l'opportunité d' une inversion de priorité . Mutex fonctionne dans l'espace utilisateur .
Sémaphore
Le sémaphore est un mécanisme de signalisation. Semaphore limite le nombre d'utilisateurs simultanés d'une ressource partagée jusqu'à un nombre maximum. Les threads peuvent demander l'accès à la ressource (décrémentation du sémaphore) et peuvent signaler qu'ils ont fini d'utiliser la ressource (incrémentation du sémaphore). Il permet à un certain nombre de threads d'accéder à des ressources partagées.L'utilisation correcte d'un sémaphore est pour la signalisation d'une tâche à une autre.Les cartes de mappage peuvent également être utilisées pour signaler d'une routine de service d'interruption (ISR) à une tâche. La signalisation d'un sémaphore est un comportement RTOS non bloquant et donc sûr ISR. Parce que cette technique élimine le besoin sujet aux erreurs de désactiver les interruptions au niveau de la tâche. Cela fonctionne dans l' espace du noyau .
La réponse peut dépendre du système d'exploitation cible. Par exemple, au moins une implémentation RTOS que je connais permettra plusieurs opérations "get" séquentielles contre un seul mutex de système d'exploitation, à condition qu'elles proviennent toutes du même contexte de thread. Les multiples get doivent être remplacés par un nombre égal de put avant qu'un autre thread ne soit autorisé à obtenir le mutex. Cela diffère des sémaphores binaires, pour lesquels un seul get est autorisé à la fois, indépendamment des contextes de thread.
L'idée derrière ce type de mutex est que vous protégez un objet en n'autorisant qu'un seul contexte à modifier les données à la fois. Même si le thread obtient le mutex puis appelle une fonction qui modifie davantage l'objet (et obtient / place le mutex protecteur autour de ses propres opérations), les opérations doivent toujours être sécurisées car elles se déroulent toutes sous un seul 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.
}
Bien sûr, lorsque vous utilisez cette fonctionnalité, vous devez être certain que tous les accès au sein d'un même thread sont vraiment sûrs!
Je ne sais pas dans quelle mesure cette approche est courante, ni si elle s'applique en dehors des systèmes que je connais. Pour un exemple de ce type de mutex, voir le ThreadX RTOS.
Les mutex ont la propriété, contrairement aux sémaphores. Bien que n'importe quel thread, dans le cadre d'un mutex, puisse obtenir un mutex déverrouillé et verrouiller l'accès à la même section critique de code, seul le thread qui a verrouillé un mutex doit le déverrouiller .
Comme beaucoup de gens l'ont mentionné ici, un mutex est utilisé pour protéger un morceau de code critique (section critique AKA.) Vous allez acquérir le mutex (verrouiller), entrer dans la section critique et libérer le mutex (déverrouiller) tous dans le même thread .
Lorsque vous utilisez un sémaphore, vous pouvez faire attendre un thread sur un sémaphore (par exemple, le thread A), jusqu'à ce qu'un autre thread (par exemple le thread B) termine la tâche, puis définit le sémaphore pour le thread A pour arrêter l'attente et continuer sa tâche.
Meilleure solution
La seule différence est
1.Mutex -> verrouiller et déverrouiller appartiennent à un thread qui verrouille le mutex.
2.Sémaphore -> Pas de propriété ie; si un thread appelle semwait (s), tout autre thread peut appeler sempost (s) pour supprimer le verrou.
MUTEX
Jusqu'à récemment, le seul verrou dormant dans le noyau était le sémaphore. La plupart des utilisateurs de sémaphores ont instancié un sémaphore avec un nombre de un et les ont traités comme un verrou d'exclusion mutuelle - une version endormie du verrou de rotation. Malheureusement, les sémaphores sont plutôt génériques et n'imposent aucune contrainte d'utilisation. Cela les rend utiles pour gérer l'accès exclusif dans des situations obscures, telles que des danses compliquées entre le noyau et l'espace utilisateur. Mais cela signifie également qu'un verrouillage plus simple est plus difficile à réaliser, et le manque de règles appliquées rend impossible toute sorte de débogage automatisé ou d'application de contraintes. À la recherche d'un verrou de sommeil plus simple, les développeurs du noyau ont introduit le mutex.Oui, comme vous en avez maintenant l'habitude, c'est un nom déroutant. Précisons. Le terme "mutex" est un nom générique pour désigner tout verrou dormant qui applique l'exclusion mutuelle, comme un sémaphore avec un nombre d'utilisation de un. Dans les noyaux Linux récents, le nom propre «mutex» est maintenant aussi un type spécifique de verrou dormant qui implémente l'exclusion mutuelle. C'est-à-dire qu'un mutex est un mutex.
La simplicité et l'efficacité du mutex proviennent des contraintes supplémentaires qu'il impose à ses utilisateurs au-delà de ce que requiert le sémaphore. Contrairement à un sémaphore, qui met en œuvre le comportement le plus élémentaire conformément à la conception originale de Dijkstra, le mutex a un cas d'utilisation plus strict et plus étroit: n Une seule tâche peut contenir le mutex à la fois. Autrement dit, le nombre d'utilisations sur un mutex est toujours un.
[1] Développement du noyau Linux, troisième édition Robert Love
Je pense que la plupart des réponses ici sont déroutantes, en particulier celles qui disent que le mutex ne peut être libéré que par le processus qui le contient, mais que le sémaphore peut être signalé par un processus. La ligne ci-dessus est un peu vague en termes de sémaphore. Pour comprendre, nous devons savoir qu'il existe deux types de sémaphore, l'un est appelé sémaphore comptant et l'autre est appelé sémaphore binaire. En comptant le sémaphore gère l'accès à n nombre de ressources où n peut être défini avant l'utilisation. Chaque sémaphore a une variable de comptage, qui conserve le compte du nombre de ressources utilisées, initialement, il est défini sur n. Chaque processus qui souhaite utiliser une ressource effectue une opération wait () sur le sémaphore (décrémentant ainsi le compte). Lorsqu'un processus libère une ressource, il effectue une opération release () (incrémentation du décompte). Lorsque le nombre devient 0, toutes les ressources sont utilisées. Après cela, le processus attend jusqu'à ce que le nombre devienne supérieur à 0. Maintenant, voici la capture, seul le processus qui détient la ressource peut augmenter le nombre, aucun autre processus ne peut augmenter le nombre, seuls les processus détenant une ressource peuvent augmenter le nombre et le processus attendre à nouveau le sémaphore vérifie et quand il voit la ressource disponible, il diminue à nouveau le nombre. Donc, en termes de sémaphore binaire, seul le processus contenant le sémaphore peut augmenter le nombre et le nombre reste nul jusqu'à ce qu'il cesse d'utiliser le sémaphore et augmente le nombre et qu'un autre processus ait la chance d'accéder au sémaphore. Maintenant, voici la capture, seul le processus qui détient la ressource peut augmenter le nombre, aucun autre processus ne peut augmenter le nombre, seuls les processus détenant une ressource peuvent augmenter le nombre et le processus en attente de sémaphore vérifie à nouveau et lorsqu'il voit la ressource disponible, il diminue à nouveau le nombre. Donc, en termes de sémaphore binaire, seul le processus contenant le sémaphore peut augmenter le nombre et le nombre reste nul jusqu'à ce qu'il cesse d'utiliser le sémaphore et augmente le nombre et qu'un autre processus ait la chance d'accéder au sémaphore. Maintenant, voici la capture, seul le processus qui détient la ressource peut augmenter le nombre, aucun autre processus ne peut augmenter le nombre, seuls les processus détenant une ressource peuvent augmenter le nombre et le processus en attente de sémaphore vérifie à nouveau et lorsqu'il voit la ressource disponible, il diminue à nouveau le nombre. Donc, en termes de sémaphore binaire, seul le processus contenant le sémaphore peut augmenter le nombre et le nombre reste nul jusqu'à ce qu'il cesse d'utiliser le sémaphore et augmente le nombre et qu'un autre processus ait la chance d'accéder au sémaphore.
La principale différence entre le sémaphore binaire et le mutex est que le sémaphore est un mécanisme de signalisation et le mutex est un mécanisme de verrouillage, mais le sémaphore binaire semble fonctionner comme un mutex qui crée de la confusion, mais les deux sont des concepts différents adaptés à différents types de travaux.