Was ist Mutex und Semaphor in Java? Was ist der Hauptunterschied?


Antworten:


115

Semaphor kann gezählt werden, während Mutex nur bis 1 zählen kann.

Angenommen, Sie haben einen Thread ausgeführt, der Clientverbindungen akzeptiert. Dieser Thread kann 10 Clients gleichzeitig verarbeiten. Dann setzt jeder neue Client das Semaphor, bis es 10 erreicht. Wenn das Semaphor 10 Flags hat, akzeptiert Ihr Thread keine neuen Verbindungen

Mutex werden normalerweise zum Schutz von Sachen verwendet. Angenommen, Ihre 10 Clients können auf mehrere Teile des Systems zugreifen. Dann können Sie einen Teil des Systems mit einem Mutex schützen. Wenn also 1 Client mit diesem Subsystem verbunden ist, sollte niemand anderes Zugriff haben. Sie können auch ein Semaphor für diesen Zweck verwenden. Ein Mutex ist ein "Semaphor für gegenseitigen Ausschluss" .


4
Das ist nicht ganz richtig. Derselbe Thread kann mehr als einmal in denselben Mutex eingeben. Daher muss eine Anzahl beibehalten werden, um sicherzustellen, dass die Ein- und Ausgänge ausgeglichen sind.
Finnw

1
@finnw, im Allgemeinen gibt es zwei Arten von Mutexen, rekursive und nicht rekursive. Verwendet Java standardmäßig den rekursiven Typ?
edA-qa mort-ora-y

2
@ edA-qa mort-ora-y, der Begriff "Mutex" wird in der Java VM- oder API-Spezifikation nicht verwendet, daher gehe ich davon aus, dass er sich auf den in jedes Objekt integrierten Monitor bezieht, der auch dem Win32-Objekt ähnlich ist, das als Mutex bezeichnet wird . Gleiches gilt für a ReentrantLock. Alle diese sind rekursiv. Mir sind keine "realen" Beispiele für nicht rekursive Mutexe bekannt (ich habe sie nur in Lehrbüchern gesehen), daher habe ich sie nicht berücksichtigt.
Finnw

2
Nicht rekursive Mutexe können mithilfe eines Semaphors mit der Nummer eins implementiert werden. Dies kann nützlich sein, wenn Sie rekursive Aufrufe verhindern möchten. Dies hat praktische Verwendungszwecke. Ich habe es persönlich in großen Projekten verwendet, um Schleifen im Initialisierungscode zu erkennen (A initialisiert B, das versucht, A erneut zu initialisieren).
Alexander Torstling

1
Im C ++ 11-Standard (C ++ 0x) ist Mutex nicht rekursiv. Sie bieten auch einen separaten 'recursive_mutex' für diejenigen, die dies benötigen. Ich weiß, dass wir hier über Java sprechen, aber dann codieren viele von uns jetzt sprachübergreifend.
Aditya Kumar Pandey

139

Leider hat jeder den wichtigsten Unterschied zwischen Semaphor und Mutex übersehen; das Konzept des " Eigentums ".

Semaphoren haben keine Vorstellung von Eigentum, dies bedeutet, dass jeder Thread ein Semaphor freigeben kann (dies kann zu vielen Problemen an sich führen, aber bei der "Todeserkennung" helfen). Während ein Mutex das Konzept des Eigentums hat (dh Sie können nur einen Mutex freigeben, den Sie erworben haben).
Das Eigentum ist unglaublich wichtig für die sichere Programmierung gleichzeitiger Systeme. Ich würde immer empfehlen, Mutex einem Semaphor vorzuziehen (aber es gibt Auswirkungen auf die Leistung).

Mutexe unterstützen möglicherweise auch die Prioritätsvererbung (die beim Problem der Prioritätsinversion helfen kann) und die Rekursion (wodurch eine Art von Deadlock beseitigt wird).

Es sollte auch darauf hingewiesen werden, dass es "binäre" Semaphoren und "zählende / allgemeine" Semaphore gibt. Das Java-Semaphor ist ein Zählsemaphor und ermöglicht daher die Initialisierung mit einem Wert größer als eins (während ein Mutex, wie bereits erwähnt, nur eine konzeptionelle Zählung von eins kann). Auf die Nützlichkeit dieses Themas wurde in anderen Beiträgen hingewiesen.

Zusammenfassend würde ich den Mutex immer über dem Semaphor empfehlen, es sei denn, Sie haben mehrere Ressourcen zu verwalten.


1
Die Antwort von Feabhas ist sehr wichtig - der Mutex überprüft den Thread, der versucht, den Mutex freizugeben, der ihn tatsächlich besitzt. Ich hatte dies als Interviewfrage, daher lohnt es sich, sich daran zu erinnern.
Andrew Pate

40

Mutex ist grundsätzlich gegenseitiger Ausschluss. Nur ein Thread kann die Ressource gleichzeitig abrufen. Wenn ein Thread die Ressource abruft, darf kein anderer Thread die Ressource abrufen, bis der Thread, dem die Ressource gehört, freigegeben wird. Alle Threads, die auf den Erwerb von Ressourcen warten, werden blockiert.

Semaphor wird verwendet, um die Anzahl der ausgeführten Threads zu steuern. Es wird einen festen Satz von Ressourcen geben. Die Ressourcenanzahl wird jedes Mal dekrementiert, wenn ein Thread denselben besitzt. Wenn die Semaphoranzahl 0 erreicht, dürfen keine anderen Threads die Ressource abrufen. Die Threads werden blockiert, bis andere Threads Ressourcen freigeben.

Kurz gesagt, der Hauptunterschied besteht darin, wie viele Threads die Ressource gleichzeitig abrufen dürfen.

  • Mutex - es ist EINS.
  • Semaphor - sein DEFINED_COUNT (so viele wie Semaphor zählen)

8

Ein Mutex wird für den seriellen Zugriff auf eine Ressource verwendet, während ein Semaphor den Zugriff auf eine Ressource auf eine festgelegte Anzahl beschränkt. Sie können sich einen Mutex als ein Semaphor mit einer Zugriffsanzahl von 1 vorstellen. Unabhängig davon, auf was Sie Ihre Semaphoranzahl eingestellt haben, können Threads auf die Ressource zugreifen, bevor die Ressource blockiert wird.



3

Ein Mutex wird oft als binäres Semaphor bezeichnet. Während ein Semaphor mit einer beliebigen Anzahl ungleich Null erstellt werden kann, ist ein Mutex konzeptionell ein Semeaphore mit einer oberen Anzahl von 1.



1

Semaphor :

Ein Zählsemaphor. Konzeptionell verwaltet ein Semaphor eine Reihe von Genehmigungen. Jeder acquire()blockiert bei Bedarf, bis eine Genehmigung verfügbar ist, und nimmt sie dann entgegen. Jeder release()fügt eine Genehmigung hinzu, wodurch möglicherweise ein blockierender Erwerber freigegeben wird. Es werden jedoch keine tatsächlichen Genehmigungsobjekte verwendet. Das Semaphor zählt nur die verfügbare Anzahl und handelt entsprechend.

Semaphore werden häufig verwendet, um die Anzahl der Threads zu beschränken, die auf eine (physische oder logische) Ressource zugreifen können

Java verfügt nicht über eine integrierte Mutex-API. Es kann jedoch als binäres Semaphor implementiert werden.

Ein auf eins initialisiertes Semaphor, das so verwendet wird, dass höchstens eine Genehmigung zur Verfügung steht, kann als gegenseitige Ausschlusssperre dienen. Dies wird allgemein als binäres Semaphor bezeichnet, da nur zwei Zustände vorliegen: eine Erlaubnis verfügbar oder null Genehmigungen verfügbar.

Bei dieser Verwendung hat das binäre Semaphor die Eigenschaft (im Gegensatz zu vielen Lock-Implementierungen), dass die "Sperre" von einem anderen Thread als dem Eigentümer freigegeben werden kann (da Semaphoren keinen Begriff des Eigentums haben) . Dies kann in einigen speziellen Kontexten nützlich sein, z. B. bei der Wiederherstellung von Deadlocks.

Also wesentliche Unterschiede zwischen Semaphore und Mutex:

  1. Semaphor beschränkt die Anzahl der Threads, um über eine zulässige Ressource auf eine Ressource zuzugreifen. Mit Mutex kann nur ein Thread auf Ressourcen zugreifen.

  2. Kein Thread besitzt Semaphore. Threads können die Anzahl der Berechtigungen durch Aufrufen acquire()und release()Methoden aktualisieren . Mutexe sollten nur durch den Faden entriegelt werden, der das Schloss hält.

  3. Wenn ein Mutex mit Bedingungsvariablen verwendet wird, gibt es eine implizite Klammer - es ist klar, welcher Teil des Programms geschützt wird. D. Dies ist nicht unbedingt der Fall für ein Semaphor, das als Go-to-of-Concurrent-Programming bezeichnet werden kann. Es ist leistungsstark, aber zu einfach, um es unstrukturiert und unbestimmt zu verwenden.


0

Mutex ist ein binäres Semaphor. Es muss mit 1 initialisiert werden, damit das First Come First Serve-Prinzip erfüllt ist. Dies bringt uns zu der anderen besonderen Eigenschaft jedes Mutex: Derjenige, der nach unten gegangen ist , muss derjenige sein, der nach oben geht . Ergo haben wir gegenseitigen Ausschluss über eine Ressource erhalten.

Jetzt konnte man sehen, dass ein Mutex ein Sonderfall des allgemeinen Semaphors ist.


0

Das Objekt der Synchronisation Semaphorimplementiert eine klassische Ampel. Eine Ampel steuert den Zugriff auf eine Ressource, die von einem Zähler gemeinsam genutzt wird. Wenn der Zähler größer als Null ist, wird der Zugriff gewährt. Wenn es Null ist, wird der Zugriff verweigert. Der Zähler zählt die Berechtigungen, die den Zugriff auf die gemeinsam genutzte Ressource ermöglichen. Um auf die Ressource zugreifen zu können, muss ein Thread die Berechtigung der Ampel erhalten. Um eine Ampel zu verwenden, versucht der Thread, der auf die gemeinsam genutzte Ressource zugreifen möchte, im Allgemeinen, eine Genehmigung zu erhalten. Wenn die Anzahl der Ampeln größer als Null ist, erhält der Thread eine Genehmigung und die Anzahl der Ampeln wird dekrementiert. Andernfalls wird der Thread gesperrt, bis er eine Berechtigung erhalten kann. Wenn der Thread nicht mehr auf die gemeinsam genutzte Ressource zugreifen muss, gibt er die Berechtigung frei, sodass die Anzahl der Ampeln erhöht wird. Wenn ein anderer Thread auf eine Genehmigung wartet, es erwirbt zu diesem Zeitpunkt eine Genehmigung. Die Semaphore-Klasse von Java implementiert diesen Mechanismus.

Semaphore hat zwei Erbauer:

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

num gibt die anfängliche Anzahl der Genehmigungen an. Dann gibt num die Anzahl der Threads an, die zu einem bestimmten Zeitpunkt auf eine gemeinsam genutzte Ressource zugreifen können. Wenn num eins ist, kann es Thread für Thread auf die Ressource zugreifen. Wenn Sie die Einstellung auf true setzen, können Sie sicherstellen, dass den Threads, auf die Sie warten, die Berechtigung in der von ihnen angeforderten Reihenfolge erteilt wird.


0

Sie vergleichen das unvergleichliche, technisch gibt es keinen Unterschied zwischen einem Semaphor und einem Mutex, es macht keinen Sinn. Mutex ist nur ein signifikanter Name wie jeder andere Name in Ihrer Anwendungslogik. Dies bedeutet, dass Sie ein Semaphor bei "1" initialisieren. Es wird im Allgemeinen zum Schutz einer Ressource oder einer geschützten Variablen verwendet, um den gegenseitigen Ausschluss sicherzustellen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.