web-dev-qa-db-fra.com

Quand devrions-nous utiliser un mutex et quand devrions-nous utiliser un sémaphore

Quand faut-il utiliser le mutex et quand utiliser le sémaphore?

97
Karthik Balaguru

Voici comment je me souviens quand utiliser quoi - 

Sémaphore: .__ Utilisez un sémaphore lorsque vous (le fil) voulez dormir jusqu'à ce qu'un autre fil vous dise de vous réveiller. Le sémaphore 'down' se produit dans un thread (producteur) et le sémaphore 'up' (pour le même sémaphore) se produit dans un autre thread (consommateur) vide - seul le fil consommateur peut dire quand un emplacement de tampon est vide. 

Mutex: .__ Utilisez un mutex lorsque vous (thread) voulez exécuter du code qui ne devrait pas être exécuté par un autre thread en même temps. Le mutex 'down' se produit dans un thread et le mutex 'up' doit se produire ultérieurement dans le même thread . Exemple: Si vous supprimez un nœud d'une liste liée globale, vous ne voulez pas qu'un autre thread débrouillez-vous avec des pointeurs pendant la suppression du nœud. Lorsque vous acquérez un mutex et êtes en train de supprimer un nœud, si un autre thread tente d'acquérir le même mutex, il sera mis en veille jusqu'à ce que vous libériez le mutex.

Spinlock: .__ Utilisez un spinlock lorsque vous voulez vraiment utiliser un mutex mais que votre thread n'est pas autorisé à dormir. Par exemple: un gestionnaire d’interruptions dans le noyau du système d’exploitation ne doit jamais dormir. Si cela se produit, le système gèlera/plantera. Si vous devez insérer un nœud dans la liste chaînée partagée globalement à partir du gestionnaire d'interruptions, procurez-vous un verrou tournant spinlock - insert node - release.

79
Annu Gogatya

Un mutex est un objet d'exclusion mutuelle, similaire à un sémaphore, mais n'autorisant qu'un casier à la fois et dont les restrictions de propriété peuvent être plus strictes qu'un sémaphore.

Cela peut être considéré comme équivalent à un sémaphore de comptage normal (avec un compte) et à l'exigence qu'il ne puisse être libéré que par le même thread qui l'a verrouillé.(une).

Un sémaphore, par contre, a un nombre arbitraire et peut être verrouillé simultanément par autant de casiers. Et il n'est peut-être pas nécessaire de le publier par le même fil que celui qui l'a revendiqué (mais, dans le cas contraire, vous devez suivre de très près qui en est actuellement responsable, un peu comme la mémoire allouée).

Ainsi, si vous avez plusieurs instances d'une ressource (par exemple trois lecteurs de bande), vous pouvez utiliser un sémaphore avec un nombre de 3. Notez que cela ne vous indique pas lequel de ces lecteurs de bande vous avez, mais simplement que vous avez un certain nombre.

De plus, avec les sémaphores, il est possible pour un même casier de verrouiller plusieurs instances d'une ressource, par exemple pour une copie bande à bande. Si vous avez une ressource (par exemple un emplacement de mémoire que vous ne voulez pas corrompre), un mutex est plus approprié.

Les opérations équivalentes sont:

Counting semaphore          Mutual exclusion semaphore
--------------------------  --------------------------
  Claim/decrease (P)                  Lock
  Release/increase (V)                Unlock

A part: au cas où vous vous seriez jamais demandé les lettres bizarres utilisées pour réclamer et libérer des sémaphores, c'est parce que l'inventeur était néerlandais. Probeer te verlagen signifie essayer de diminuer tandis que verhogen signifie augmenter.


(une) ... ou cela peut être considéré comme quelque chose de totalement distinct d'un sémaphore, ce qui peut être plus sûr compte tenu de leurs utilisations presque toujours différentes.

54
paxdiablo

Il est très important de comprendre qu'un mutex n'est pas un sémaphore avec le nombre 1!

C'est la raison pour laquelle il y a des choses comme les sémaphores binaires (qui sont vraiment des sémaphores avec le compte 1).

La différence entre un mutex et un binaire-sémaphore est le principe de propriété:

Un mutex est acquis par une tâche et doit donc également être libéré par la même tâche ..__ Ceci permet de résoudre plusieurs problèmes liés aux sémaphores binaires (libération accélérée, impasse récursive et inversion de priorité).

Mise en garde: j'ai écrit "rend possible", si et comment ces problèmes sont résolus est à la mise en œuvre du système d'exploitation.

Comme le mutex doit être libéré par la même tâche, la synchronisation des tâches n’est pas très bonne. Mais si elles sont combinées avec des variables de condition, vous obtenez des blocs de construction très puissants pour la construction de toutes sortes de primitives ipc.

Donc, ma recommandation est la suivante: si vous avez correctement implémenté des mutex et des variables de condition (comme avec les commandes POSIX), utilisez-les.

Utilisez des sémaphores uniquement s'ils correspondent exactement au problème que vous tentez de résoudre. N'essayez pas de créer d'autres primitives (par exemple, rw-locks sur des sémaphores, utilisez des mutex et des variables de condition).

Il y a beaucoup de malentendus mutex et sémaphores. La meilleure explication que j'ai trouvée jusqu'ici se trouve dans cet article en 3 parties:

Mutex contre les sémaphores - Partie 1: Les sémaphores

Mutex vs Semaphores - Partie 2: Le Mutex

Mutex vs Semaphores - Troisième partie (dernière partie): Problèmes d'exclusion mutuelle

43
Peer Stritzinger

Bien que la réponse de @opaxdiablo soit tout à fait correcte, je voudrais souligner que le scénario d'utilisation des deux choses est très différent. Le mutex est utilisé pour empêcher que des parties de code ne s'exécutent en même temps. Les sémaphores servent à indiquer à un thread d'exécuter un autre thread. 

/* Task 1 */
pthread_mutex_lock(mutex_thing);
    // Safely use shared resource
pthread_mutex_unlock(mutex_thing);



/* Task 2 */
pthread_mutex_lock(mutex_thing);
   // Safely use shared resource
pthread_mutex_lock(mutex_thing);

Le scénario de sémaphore est différent:

/* Task 1 - Producer */
sema_post(&sem);   // Send the signal

/* Task 2 - Consumer */
sema_wait(&sem);   // Wait for signal

Voir http://www.netrino.com/node/202 pour plus d'explications.

13
Patrick Schlüter

Voir "L'exemple de la toilette" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :

Mutex:

Est-ce une clé pour une toilette. Une personne peut avoir la clé - occuper les toilettes - à la fois. Une fois l'opération terminée, la personne donne (libère) la clé à la prochaine personne de la file d'attente.

Officiellement: "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 plusieurs threads. Un objet mutex ne permet qu’un thread dans une section contrôlée, forçant les autres threads tentant d’accéder à cette section à attendre jusqu'à ce que le premier thread se termine. " Réf.: Bibliothèque de développeurs Symbian

(Un mutex est vraiment un sémaphore de valeur 1.)

Sémaphore:

Est-ce le nombre de clés de toilette identiques gratuites? Exemple, disons que nous avons quatre toilettes avec des serrures et des clés identiques. Le nombre de sémaphores - le nombre de clés - est réglé sur 4 au début (les quatre toilettes sont gratuites), puis la valeur du compte est décrémentée au fur et à mesure que les personnes entrent. Si toutes les toilettes sont pleines, c'est-à-dire. il ne reste plus de clés libres, le nombre de sémaphores est 0. Maintenant, quand éq. une personne quitte les toilettes, le sémaphore est augmenté à 1 (une touche libre) et est donné à la personne suivante dans la file d'attente.

Officiellement: "Un sémaphore limite le nombre d'utilisateurs simultanés d'une ressource partagée à un nombre maximal. 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). " Ref: Bibliothèque de développement Symbian

8
fornwall

Essayer de ne pas paraître loufoque, mais je ne peux pas m'en empêcher.

Votre question devrait être quelle est la différence entre le mutex et les sémaphores? Et pour être plus précise, la question devrait être: «Quelle est la relation entre le mutex et les sémaphores?

(J'aurais ajouté cette question, mais je suis presque à 100% sûr qu'un modérateur trop zélé la fermerait comme un doublon sans comprendre la différence entre la différence et la relation.)

Dans la terminologie des objets, nous pouvons observer que:

observation.1 Le sémaphore contient du mutex

observation.2 Le mutex n'est pas un sémaphore et le sémaphore n'est pas un mutex. 

Il existe des sémaphores qui agissent comme s’ils étaient un mutex, appelés sémaphores binaires, mais ils flippent pas mutex.

Il existe un ingrédient spécial appelé Signaling (posix utilise condition_variable pour ce nom), nécessaire pour créer un sémaphore à partir d'un mutex . Considérez-le comme une source de notification. Si deux ou plusieurs threads sont abonnés à la même source de notification, il est alors possible de leur envoyer un message à ONE ou à ALL, afin de les réactiver.

Il pourrait y avoir un ou plusieurs compteurs associés aux sémaphores, qui sont gardés par mutex. Le scénario le plus simple pour le sémaphore, il existe un seul compteur qui peut être 0 ou 1.

C’est là que la confusion s’installe comme une pluie de mousson.

Un sémaphore avec un compteur qui peut être 0 ou 1 n'est pas un mutex.

Mutex a deux états (0,1) et une propriété (tâche). Sémaphore a un mutex, des compteurs et une variable de condition.

Maintenant, utilisez votre imagination, et chaque combinaison d’utilisation de compteur et de moment de signalisation peut constituer un type de sémaphore.

  1. Compteur simple avec la valeur 0 ou 1 et signalant que la valeur passe à 1, puis déverrouille l’un des types en attente sur le signal == Sémaphore binaire

  2. Compteur simple avec une valeur de 0 à N et signalant que la valeur passe à moins de N et se verrouille/attend lorsque la valeur est N == Sémaphore de comptage 

  3. Compteur simple avec une valeur de 0 à N et signalant que la valeur passe à N, et verrouillant/attendant lorsque la valeur est inférieure à N == Sémaphore de barrière (ainsi s’ils ne l’appellent pas, ils le devraient.)

Maintenant à votre question, quand utiliser quoi. (OU plutôt question correcte version.3 quand utiliser mutex et quand utiliser binaire-sémaphore, car il n'y a aucune comparaison avec sémaphore non-binaire.) Utilisez mutex quand 1. vous voulez un comportement personnalisé, qui n'est pas fourni par le sémaphore binaire, tel que verrouillé au tour ou verrou rapide ou verrou récursif . Vous pouvez généralement personnaliser des mutex avec des attributs, mais la personnalisation d'un sémaphore n'est rien d'autre que l'écriture d'un nouveau sémaphore 2. vous voulez une primitive plus rapide OR légère

Utilisez des sémaphores, lorsque ce que vous voulez est exactement fourni par celui-ci. 

Si vous ne comprenez pas ce qui est fourni par votre implémentation de binaire-sémaphore, alors à mon humble avis, utilisez mutex.

Et enfin, lisez un livre plutôt que de vous fier à SO.

7
Ajeet Ganga

Je pense que la question devrait être la différence entre le sémaphore mutex et binaire.

Mutex = C'est un mécanisme de verrouillage de propriété, seul le thread qui acquiert le verrou peut libérer le verrou.

sémaphore binaire = Il s’agit plus d’un mécanisme de signalisation, tout autre thread plus prioritaire, si vous le souhaitez, peut signaler et prendre le verrou. 

5
Saurabh Sengar

Mutex est de protéger la ressource partagée.
Sémaphore est chargé d’envoyer les threads.

Mutex:
Imaginez qu'il y ait des billets à vendre. Nous pouvons simuler un cas où de nombreuses personnes achètent les billets en même temps: chaque personne est un fil conducteur pour acheter des billets. Nous devons évidemment utiliser le mutex pour protéger les tickets, car il s’agit de la ressource partagée.


Sémaphore:
Imaginez que nous devions faire un calcul comme ci-dessous:

c = a + b;

Nous avons également besoin d’une fonction geta() pour calculer a, d’une fonction getb() pour calculer b et d’une fonction getc() pour effectuer le calcul c = a + b.

De toute évidence, nous ne pouvons pas faire le c = a + b à moins que geta() et getb() aient été terminés.
Si les trois fonctions sont trois threads, nous devons envoyer les trois threads.

int a, b, c;
void geta()
{
    a = calculatea();
    semaphore_increase();
}

void getb()
{
    b = calculateb();
    semaphore_increase();
}

void getc()
{
    semaphore_decrease();
    semaphore_decrease();
    c = a + b;
}

t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);

Avec l'aide du sémaphore, le code ci-dessus peut vous assurer que t3 ne fera pas son travail jusqu'à ce que t1 et t2 aient accompli leur travail.

Dans un mot, le sémaphore consiste à exécuter les threads en tant qu'ordre logique tandis que mutex protège les ressources partagées.
Donc, ils ne sont PAS la même chose, même si certaines personnes disent toujours que le mutex est un sémaphore spécial avec la valeur initiale 1. Vous pouvez le dire aussi, mais veuillez noter qu’ils sont utilisés dans des cas différents. Ne remplacez pas l'un par l'autre, même si vous pouvez le faire.

3
Yves

Comme il a été souligné, un sémaphore avec un compte est la même chose qu'un sémaphore "binaire" qui est la même chose qu'un mutex.

Les principales choses que j'ai vues avec des sémaphores avec un nombre supérieur à celui utilisé sont les situations de producteur/consommateur dans lesquelles vous avez une file d'attente d'une certaine taille fixe.

Vous avez alors deux sémaphores. Le premier sémaphore est initialement défini sur le nombre d'éléments de la file d'attente et le deuxième sur 0. Le producteur effectue une opération P sur le premier sémaphore et l'ajoute à la file d'attente. et effectue une opération V sur la seconde. Le consommateur effectue une opération P sur le deuxième sémaphore, le retire de la file d'attente, puis effectue une opération V sur le premier.

De cette façon, le producteur est bloqué lorsqu'il remplit la file d'attente et le consommateur est bloqué lorsque la file d'attente est vide.

1
Omnifarious

Un mutex est un cas particulier d'un sémaphore. Un sémaphore permet à plusieurs threads d'entrer dans la section critique. Lors de la création d'un sémaphore, vous définissez le mode d'utilisation des threads dans la section critique. Bien entendu, votre code doit pouvoir gérer plusieurs accès à cette section critique.

1
Frode Akselsen

Toutes les réponses ci-dessus sont de bonne qualité, mais celle-ci est juste à mémoriser. Le nom Mutex est dérivé demutuellement exclusifvous êtes donc motivé pour penser à un verrou mutex comme à une exclusion mutuelle deux comme dans un seul à la fois, et si je le possédais, vous ne pourrez l'avoir qu'après l'avoir relâché.En revanche, ce cas n'existe pas pour Sémaphore est comme un feu de signalisation (que le mot Sémaphore signifie aussi).

0
Nishant Sondhi