Réponses:
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" .
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.
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.
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?
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.
Un sémaphore est un mécanisme de synchronisation de comptage, un mutex ne l'est pas.
Cette question a des réponses pertinentes et un lien vers les conseils Java officiels: Existe - t-il un Mutex en Java?
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. Chacunrelease()
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:
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.
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.
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.
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.
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é.
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.