Qu'est-ce que le mutex et le sémaphore en Java? Quelle est la principale différence?

Réponses:

115

Le sémaphore peut être compté, tandis que le mutex ne peut compter que jusqu'à 1.

Supposons que vous ayez un thread en cours d'exécution qui accepte les connexions client. Ce thread peut gérer 10 clients simultanément. Ensuite, chaque nouveau client définit le sémaphore jusqu'à ce qu'il atteigne 10. Lorsque le sémaphore a 10 indicateurs, votre thread n'acceptera pas de nouvelles connexions

Les mutex sont généralement utilisés pour garder des objets. Supposons que vos 10 clients puissent accéder à plusieurs parties du système. Ensuite, vous pouvez protéger une partie du système avec un mutex. Ainsi, lorsqu'un client est connecté à ce sous-système, personne d'autre ne devrait y avoir accès. Vous pouvez également utiliser un sémaphore à cette fin. Un mutex est un "sémaphore d'exclusion mutuelle" .

Eric
la source
4
Ce n'est pas tout à fait vrai. Le même thread peut entrer le même mutex plus d'une fois, donc un décompte doit être maintenu pour s'assurer que les entrées et sorties sont équilibrées.
finlandais
1
@finnw, il existe en général deux types de mutex, récursifs et non récursifs. Java utilise-t-il par défaut le type récursif?
edA-qa mort-ora-y
2
@ edA-qa mort-ora-y, le terme "Mutex" n'est pas utilisé dans la spécification de la VM Java ou de l'API, donc je suppose qu'il fait référence au moniteur intégré à chaque objet, qui est également similaire à l'objet Win32 appelé Mutex . La même chose s'applique à a ReentrantLock. Tous ces éléments sont récursifs. Je ne connais aucun exemple «réel» de mutex non récursifs (je ne les ai vus que dans les manuels) donc je ne les ai pas considérés.
finnw
2
Les mutex non récursifs peuvent être implémentés en utilisant un sémaphore avec un compte. Cela peut être utile si vous souhaitez empêcher les appels récursifs. Cela a des utilisations pratiques, je l'ai personnellement utilisé dans de grands projets pour détecter des boucles dans le code d'initialisation (A initialise B qui essaie à nouveau d'initialiser A).
Alexander Torstling
1
Dans la norme C ++ 11 (C ++ 0x), mutex est non récursif. Ils fournissent également un 'recursive_mutex' séparé pour ceux qui en ont besoin. Je sais que nous parlons de Java ici, mais beaucoup d'entre nous codent maintenant dans plusieurs langues.
Aditya Kumar Pandey
139

Malheureusement, tout le monde a manqué la différence la plus importante entre le sémaphore et le mutex; le concept de « propriété ».

Les sémaphores n'ont aucune notion de propriété, cela signifie que n'importe quel thread peut libérer un sémaphore (cela peut conduire à de nombreux problèmes en soi mais peut aider à la "détection de la mort"). Alors qu'un mutex a le concept de propriété (c'est-à-dire que vous ne pouvez libérer qu'un mutex que vous avez acquis).
La propriété est extrêmement importante pour une programmation sûre des systèmes concurrents. Je recommanderais toujours d'utiliser mutex de préférence à un sémaphore (mais il y a des implications sur les performances).

Les mutex peuvent également prendre en charge l'héritage de priorité (qui peut aider à résoudre le problème d'inversion de priorité) et la récursivité (éliminant un type de blocage).

Il faut également signaler qu'il existe des sémaphores «binaires» et des sémaphores «comptage / général». Le sémaphore de Java est un sémaphore de comptage et permet donc de l'initialiser avec une valeur supérieure à un (alors que, comme indiqué, un mutex ne peut compter qu'un seul). L'utilité de ceci a été soulignée dans d'autres articles.

Donc, pour résumer, à moins que vous n'ayez plusieurs ressources à gérer, je recommanderais toujours le mutex sur le sémaphore.

feabhas
la source
1
La réponse de Feabhas est assez importante - le mutex vérifie que le thread qui tente de libérer le mutex le possède réellement. J'ai eu cela comme question d'entrevue, donc ça vaut la peine d'essayer de s'en souvenir.
andrew pate
40

Mutex est essentiellement une exclusion mutuelle. Un seul thread peut acquérir la ressource à la fois. Lorsqu'un thread acquiert la ressource, aucun autre thread n'est autorisé à acquérir la ressource jusqu'à ce que le thread propriétaire de la ressource libère. Tous les threads en attente d'acquisition de ressources seraient bloqués.

Le sémaphore est utilisé pour contrôler le nombre de threads en cours d'exécution. Il y aura un ensemble fixe de ressources. Le nombre de ressources sera décrémenté à chaque fois qu'un thread possède la même chose. Lorsque le nombre de sémaphores atteint 0, aucun autre thread n'est autorisé à acquérir la ressource. Les threads sont bloqués jusqu'à ce que d'autres threads possédant des ressources libèrent.

En bref, la principale différence est combien de threads sont autorisés à acquérir la ressource à la fois?

  • Mutex - c'est UN.
  • Sémaphore - son DEFINED_COUNT, (autant que le nombre de sémaphores)
un J.
la source
8

Un mutex est utilisé pour l'accès en série à une ressource tandis qu'un sémaphore limite l'accès à une ressource jusqu'à un nombre défini. Vous pouvez considérer un mutex comme un sémaphore avec un nombre d'accès de 1. Quel que soit le paramètre sur lequel vous définissez votre nombre de sémaphores, les threads peuvent accéder à la ressource avant que la ressource ne soit bloquée.

Jason Coco
la source
3

Un sémaphore est un mécanisme de synchronisation de comptage, un mutex ne l'est pas.

Brian Rasmussen
la source
3

Un mutex est souvent appelé sémaphore binaire. Alors qu'un sémaphore peut être créé avec n'importe quel décompte non nul, un mutex est conceptuellement un sémaphore avec un décompte supérieur de 1.

Sean
la source
1

Sémaphore :

Un sémaphore comptant. Conceptuellement, un sémaphore maintient un ensemble de permis. Chaque acquire()bloc si nécessaire jusqu'à ce qu'un permis soit disponible, puis le prend. Chacun release()ajoute un permis, libérant potentiellement un acquéreur bloquant. Cependant, aucun objet de permis réel n'est utilisé; le sémaphore tient simplement un compte du nombre disponible et agit en conséquence.

Les sémaphores sont souvent utilisés pour limiter le nombre de threads qui peuvent accéder à une ressource (physique ou logique)

Java n'a pas d'API Mutex intégrée. Mais il peut être implémenté en tant que sémaphore binaire.

Un sémaphore initialisé à un, et qui est utilisé de telle sorte qu'il n'a au plus qu'un permis disponible, peut servir de verrou d'exclusion mutuelle. Ceci est plus communément appelé sémaphore binaire, car il n'a que deux états: un permis disponible ou zéro permis disponible.

Lorsqu'il est utilisé de cette manière, le sémaphore binaire a la propriété (contrairement à de nombreuses implémentations de Lock), que le "verrou" peut être libéré par un thread autre que le propriétaire (car les sémaphores n'ont aucune notion de propriété) . Cela peut être utile dans certains contextes spécialisés, tels que la reprise après blocage.

Donc les principales différences entre Semaphore et Mutex:

  1. Le sémaphore limite le nombre de threads pour accéder à une ressource via les autorisations. Mutex permet à un seul thread d'accéder à la ressource.

  2. Aucun thread ne possède Semaphore. Les threads peuvent mettre à jour le nombre d'autorisations en appelant acquire()et des release()méthodes. Les mutex ne doivent être déverrouillés que par le fil qui maintient le verrou.

  3. Lorsqu'un mutex est utilisé avec des variables de condition, il y a un bracketing implicite - il est clair quelle partie du programme est protégée . Ce n'est pas nécessairement le cas pour un sémaphore, que l'on pourrait appeler le go to de la programmation concurrente - il est puissant mais trop facile à utiliser de manière non structurée et indéterminée.

Ravindra babu
la source
0

Mutex est un sémaphore binaire. Il doit être initialisé avec 1 pour que le principe du premier arrivé, premier servi soit respecté. Cela nous amène à l'autre propriété spéciale de chaque mutex: celui qui a fait tomber , doit être celui qui a fait vers le haut . Ergo, nous avons obtenu une exclusion mutuelle sur certaines ressources.

Vous pouvez maintenant voir qu'un mutex est un cas particulier de sémaphore général.

dim8
la source
0

L'objet de la synchronisation Sémaphoremet en œuvre un feu de signalisation classique. Un feu de signalisation contrôle l'accès à une ressource partagée par un compteur. Si le compteur est supérieur à zéro, l'accès est accordé; S'il est égal à zéro, l'accès est refusé. Le compteur compte les autorisations qui permettent d'accéder à la ressource partagée. Ensuite, pour accéder à la ressource, un thread doit recevoir l'autorisation du feu de signalisation. En général, pour utiliser un feu de signalisation, le thread qui souhaite accéder à la ressource partagée tente d'acquérir un permis. Si le nombre de feux de signalisation est supérieur à zéro, le thread acquiert un permis et le nombre de feux de signalisation est décrémenté. Sinon, le thread est verrouillé jusqu'à ce qu'il puisse obtenir une autorisation. Lorsque le thread n'a plus besoin d'accéder à la ressource partagée, il libère l'autorisation, de sorte que le nombre de feux de signalisation est augmenté. S'il y a un autre thread en attente d'un permis, il acquiert un permis à ce moment-là. La classe Semaphore de Java implémente ce mécanisme.

Semaphore a deux constructeurs:

Semaphore(int num)
Semaphore(int num, boolean come)

num spécifie le décompte initial du permis. Puis num spécifie le nombre de threads qui peuvent accéder à une ressource partagée à un moment donné. Si num est un, il peut accéder à la ressource un thread à la fois. En définissant come as true, vous pouvez garantir que les threads que vous attendez reçoivent l'autorisation dans l'ordre qu'ils ont demandé.

Amarildo
la source
0

Vous comparez l'incomparable, techniquement il n'y a pas de différence entre un sémaphore et un mutex cela n'a pas de sens. Mutex est juste un nom significatif comme n'importe quel nom dans la logique de votre application, cela signifie que vous initialisez un sémaphore à "1", il est généralement utilisé pour protéger une ressource ou une variable protégée pour assurer l'exclusion mutuelle.

Marwen Trabelsi
la source