Différence entre sémaphore binaire et mutex


819

Y a-t-il une différence entre un sémaphore binaire et un mutex ou sont-ils essentiellement les mêmes?


11
Ils sont sémantiquement les mêmes, mais dans la pratique, vous remarquerez des différences étranges (en particulier sous Windows).
Michael Foukarakis

5
@Michael Foukarakis: Quelles sont les différences étranges?
Philipp

2
Je suppose que bizarre n'était pas l'expression correcte. Un mutex prend également en charge la propriété et parfois la rentrée. C'est le cas sous Windows. De plus, les sémaphores dans Windows sont implémentés au-dessus des objets Event, cependant, je ne suis pas sûr des implications pratiques de cela.
Michael Foukarakis


2
@philipxy Bien caché 'rn' à la place de 'm'.
Mooncrater

Réponses:


691

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:

  • La tâche B est en attente en attendant que quelque chose se produise (un capteur est déclenché par exemple).
  • Les déclenchements de capteur et une routine de service d'interruption s'exécutent. Il doit notifier une tâche du voyage.
  • La tâche B doit s'exécuter et prendre les mesures appropriées pour le déclenchement du capteur. Revenez ensuite à l'attente.

   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.


12
Un mutex n'est-il pas meilleur qu'un sémaphore binaire alors? Puisque cela n'a pas de sens si quelqu'un libère un verrou qu'il ne détient pas réellement.
Pacerier

111
Ils ont des objectifs différents. Mutex est pour l'accès exclusif à une ressource. Un sémaphore binaire doit être utilisé pour la synchronisation (c'est-à-dire "Hé quelqu'un! Cela s'est produit!"). Le «donneur» binaire informe simplement quiconque «preneur» que ce qu'il attendait est arrivé.
Benoit

5
@Pacerier Vous confondez le but. Un mutex est destiné à protéger une région critique. Vous avez raison, il n'est pas logique d'utiliser un sémaphore binaire. Je mettrai à jour la réponse pour expliquer le but de chacun.
Benoit

4
@Benoit Alors pouvons-nous dire que Mutex sont utilisés pour l'atomicité et le sémaphore binaire pour la perspective de la commande, car la tâche B attendra que la tâche A signale la libération du verrou en s'assurant intrinsèquement de la commande des opérations sur une structure de données?
abhi

1
@abhi C'est une bonne façon de voir les choses pour le Mutex. Cependant, selon le système d'exploitation, vous pouvez avoir plusieurs destinataires en attente sur un sémaphore binaire. Dans ce cas, un seul client recevra le sem binaire. Les autres attendraient une autre. L'ordre de réception est-il connu ou garanti? Dépend de l'OS.
Benoit

446
  • Un mutex ne peut être libéré que par le thread qui l'a acquis .
  • Un sémaphore binaire peut être signalé par n'importe quel thread (ou processus).

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.


34
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
daisy

15
@ warl0ck Selon la page de manuel de pthread_mutex_lock linux.die.net/man/3/pthread_mutex_lock : "Si le type de mutex est PTHREAD_MUTEX_ERRORCHECK, une vérification d'erreur doit être fournie .... Si un thread tente de déverrouiller un mutex qu'il a non verrouillé ou un mutex déverrouillé, une erreur doit être renvoyée. "
2013

47
@ warl0ck Veuillez consulter stackoverflow.com/a/5492499/385064 'Pthreads a 3 types de mutex différents: mutex rapide, mutex récursif et mutex de vérification d'erreur. Vous avez utilisé un mutex rapide qui, pour des raisons de performances, ne vérifiera pas cette erreur. Si vous utilisez le contrôle d'erreur mutex sous Linux, vous constaterez que vous obtenez les résultats escomptés.
FrostNovaZzz

1
Dans notre code, nous avons également utilisé le mutex à des fins de synchronisation.Le thread qui verrouille le mutex a à nouveau essayé de verrouiller le mutex.Ensuite, il passe à l'état bloqué.Ce que nous avons vu, c'est que nous sommes en mesure de le déverrouiller à partir d'un autre thread. synchronisation entre les deux.Nous utilisons uniquement la norme posix.Ainsi, la principale différence entre le mutex et le sémaphore binaire semble vague.
achoora

1
@achoora Je conviens qu'il est faux de spécialiser le sémaphore pour la synchronisation. En fait, tous les pipelines mutex, binaire-sémaphore, barrière, sont des schémas de synchronisation différents. Du point de vue de la conception, les mutex ressemblent davantage à un modèle d'état où l'algorithme sélectionné par l'état peut changer l'état. Les sémaphores binaires ressemblent davantage à un modèle de stratégie où l'algorithme externe peut changer l'état et éventuellement l'algorithme / la stratégie sélectionnée pour s'exécuter.
shuva

442

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


234
... mais cela concerne mutex vs sémaphore de comptage. La question a été posée sur binaire.
Roman Nikitchenko

24
Certes, ce qui est dit par David est correct, mais ce n'est PAS la réponse à la question posée. La réponse de Mladen Jankovic est la réponse à la question posée, où l'on fait la différence entre "binaire-sémaphore" et "mutex".
Ajeet Ganga

13
Malheureusement, cette réponse incorrecte a plus de votes que la meilleure réponse par @Benoit
NeonGlow

6
Cette réponse est trompeuse et n'aurait dû être comparée qu'avec le sémaphore binaire.
Hemanth

3
Cela montre également un problème avec l'utilisation d'un sémaphore de comptage pour protéger une ressource partagée: si les clés sont en effet identiques et qu'une toilette est déverrouillée à l'aide d'une clé et qu'il n'y a pas d'autre mécanisme pour distribuer l'utilisation de la cellule, alors: (1) le premier l'utilisateur déverrouille, entre et commence à utiliser la première cellule. (2) le prochain utilisateur déverrouille, entre et commence à utiliser la première cellule ...
Technophile

151

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.


Merci pour le lien, les explications y sont excellentes. Le lien a changé: feabhas.com/blog/2009/09/… (Utilisez <Préc et Suivant> pour naviguer vers les deux autres articles.
Aaron H.

@Aaron J'ai corrigé les liens
Juge Maygarden

Remarque - le manque de propriété empêche également le système d'exploitation de contourner l'inversion de priorité. Pour cette raison, j'utilise généralement des variables de condition par opposition aux sémaphores pour les architectures producteur / consommateur.
kgriffs

1
+1 pour les excellents liens vers les articles. Le meilleur article expliquant le sémaphore et le mutex avec "ce que c'est" et "ce que ça fait" computing.llnl.gov/tutorials/pthreads J'avais utilisé cet article comme référence derrière la scène, ce qui explique techniquement tout sur mutex / conditionnels et autres constructions construites sur leur sommet comme sémaphore / barrière / lecteur-écrivain, mais nulle part explicite et concise sur les problèmes rencontrés avec les constructions. Bref c'est référence. :)
Ajeet Ganga

plus facile à comprendre que les autres réponses.
BinaryTreeee

101

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 .

Source: http://www.geeksforgeeks.org/mutex-vs-semaphore/


42

Leur sémantique de synchronisation est très différente:

  • les mutex permettent la sérialisation de l'accès à une ressource donnée, c'est-à-dire que plusieurs threads attendent un verrou, un à la fois et comme dit précédemment, le thread possède le verrou jusqu'à ce qu'il soit fait: seul ce thread particulier peut le déverrouiller.
  • un sémaphore binaire est un compteur de valeur 0 et 1: une tâche qui le bloque jusqu'à ce qu'une tâche fasse un sem_post. Le sémaphore annonce qu'une ressource est disponible et fournit le mécanisme permettant d'attendre qu'il soit signalé comme étant disponible.

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


23

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.


1
Je ne pense pas qu'il soit courant qu'un mutex soit implémenté avec des verrous tournants. Sur une machine Uni-proc, ce serait absolument terrible pour les performances.
Evan Teran

Normalement, vous n'utilisez des verrous tournants que sur des systèmes multiprocesseurs.
ConcernedOfTunbridgeWells

Même sur SMP, après avoir tourné plusieurs fois, vous retombez en veille / veille assistée par le système d'exploitation. (par exemple Linux futexappel 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.
Peter Cordes

19

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.


"peut être signalé par un thread différent" qu'est-ce que cela signifie donner un exemple.
Myanju

15

Mutex: Supposons que nous ayons le thread de section critique T1 qui souhaite y accéder, il suit les étapes ci-dessous. T1:

  1. Fermer à clé
  2. Utiliser la section critique
  3. Ouvrir

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:

  1. wait (s) // initialement, la valeur de s est une après l'appel de wait, sa valeur a été diminuée de un, c'est-à-dire 0
  2. Utiliser la section critique
  3. signal (s) // maintenant la valeur de s est augmentée et elle devient 1

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


12

Sous Windows, il existe deux différences entre les mutex et les sémaphores binaires:

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

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


4
Bonne réponse. Dans # 2, vous décrivez un mutex récursif - tous les mutex ne sont pas nécessairement récursifs. Par exemple, cs.wustl.edu/~schmidt/ACE.FAQ.html#Q14
Dan

10

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 !,

  • avec "mutex" cela ne peut pas arriver. Aucun autre fil ne peut déverrouiller le verrou de votre fil
  • avec "binaire-sémaphore" cela peut arriver. Tout autre fil peut déverrouiller le verrou de votre fil

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


10

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"


9

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


8

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.


6

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.


i) Mauvais. ii) Source? iii) Cela dépend.
curiousguy

6

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.


5

Mutex travaille sur le blocage des régions critiques, mais Semaphore travaille sur le compte.


5

http://www.geeksforgeeks.org/archives/9102 discute en détail.

Mutexest un mécanisme de verrouillage utilisé pour synchroniser l'accès à une ressource. Semaphoreest le mécanisme de signalisation.

C'est au programmeur s'il veut utiliser un sémaphore binaire à la place de mutex.


4

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.


Dans quels cas spécifiques l'équité est-elle garantie pour les sémaphores mais pas pour les mutex?
curiousguy

1
Posix a des exigences spécifiques qui doivent être fil Réveillé par sem_post()pour SCHED_FIFOet 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.
jilles

4

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.


4

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:

  • Libération accidentelle
  • Blocage récursif
  • Tâche Deadlock

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 EDEADLKsi vous essayez de verrouiller le même deux fois et EPERMsi 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");

4

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.


Si vous lisez les autres réponses, il est clair que le concept de «propriété» n'a de sens que pour les mutex, pas les sémaphores. Les sémaphores peuvent être utilisés pour des choses comme un fil de discussion, permettant aux autres fils de savoir que le traitement d'un bloc de données est effectué; résultats prêts à être lus.
Peter Cordes

2

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.


2

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 .


1

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.


2
Le type de mutex dont vous parlez est appelé "mutex récursif" et doit être évité car il est lent et a tendance à promouvoir une mauvaise conception: (voir David Butenhof: zaval.org/resources/library/butenhof1.html )
gaspard

D'accord. Sur ce système d'exploitation particulier, j'utilise le service mutex où je tiens à préciser que le code est pour «l'exclusion mutuelle» et non le comptage de références, mais je n'utilise pas la fonction récursive par peur d'un déroulement laid. Pourtant, dans le contexte de la question, c'est une différence importante entre un "mutex" et un "sémaphore binaire".
Casey Barker

1

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 .


qu'est-ce que la propriété? Vous voulez dire que le contexte qui acquiert mutex ne peut que le retirer. ??
Raulp

1

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.


1

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.


1

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. Celui qui a verrouillé un mutex doit le déverrouiller. Autrement dit, vous ne pouvez pas verrouiller un mutex dans un contexte, puis le déverrouiller dans un autre. Cela signifie que le mutex n'est pas adapté aux synchronisations plus compliquées entre le noyau et l'espace utilisateur. Cependant, la plupart des cas d'utilisation se verrouillent et se déverrouillent proprement à partir du même contexte.
  2. Les verrous et déverrouillages récursifs ne sont pas autorisés. Autrement dit, vous ne pouvez pas acquérir récursivement le même mutex, et vous ne pouvez pas déverrouiller un mutex déverrouillé.
  3. Un processus ne peut pas quitter tout en maintenant un mutex.
  4. Un mutex ne peut pas être acquis par un gestionnaire d'interruption ou la moitié inférieure, même avec mutex_trylock ().
  5. Un mutex ne peut être géré que via l'API officielle: il doit être initialisé via les méthodes décrites dans cette section et ne peut pas être copié, initialisé à la main ou réinitialisé.

[1] Développement du noyau Linux, troisième édition Robert Love


1

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.