Antworten:
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" .
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.
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.
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.
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.
Ein Semaphor ist ein Zählsynchronisationsmechanismus, ein Mutex nicht.
Diese Frage enthält relevante Antworten und einen Link zur offiziellen Java-Anleitung: Gibt es einen Mutex in Java?
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. Jederrelease()
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:
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.
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.
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.
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.
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.
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.