998 Stimmen

Unterschied zwischen binärem Semaphor und Mutex

Gibt es einen Unterschied zwischen einem binären Semaphor und einem Mutex oder sind sie im Wesentlichen dasselbe?

18 Stimmen

Semantisch sind sie gleich, aber in der Praxis werden Sie seltsame Unterschiede feststellen (besonders unter Windows).

10 Stimmen

@Michael Foukarakis: Was sind die merkwürdigen Unterschiede?

5 Stimmen

Ich nehme an, seltsam war nicht der richtige Ausdruck. Ein Mutex unterstützt auch den Besitz und manchmal den Wiedereintritt. Dies ist in Windows der Fall. Darüber hinaus sind Semaphoren in Windows auf Event-Objekte implementiert, aber ich bin mir nicht sicher, welche praktischen Auswirkungen dies hat.

49voto

ppi Punkte 1437

Ihre Synchronisierungssemantik ist sehr unterschiedlich:

  • Mutexe ermöglichen die Serialisierung des Zugriffs auf eine bestimmte Ressource, d.h. mehrere Threads warten auf eine Sperre, einer nach dem anderen, und wie bereits gesagt, der Thread besitzt das Schloss, bis es fertig ist: nur dieses spezielle Thema freischalten kann.
  • ein binärer Semaphor ist ein Zähler mit den Werten 0 und 1: eine Aufgabe blockiert ihn, bis cualquier Aufgabe macht einen sem_post. Der Semaphor zeigt an, dass eine Ressource verfügbar ist, und bietet den Mechanismus, um zu warten, bis sie als verfügbar gemeldet wird.

So kann man eine Mutex als Token sehen, das von Task zu Task weitergegeben wird, und eine Semaphore als Ampel (sie Signale jemand, dass es weitergehen kann).

33voto

Auf theoretischer Ebene unterscheiden sie sich semantisch nicht. Sie können eine Mutex mit Semaphoren implementieren oder umgekehrt (siehe aquí für ein Beispiel). In der Praxis sind die Implementierungen unterschiedlich, und sie bieten leicht unterschiedliche Dienste an.

Der praktische Unterschied (in Bezug auf die sie umgebenden Systemdienste) besteht darin, dass die Implementierung eines Mutex darauf abzielt, ein leichtgewichtigerer Synchronisierungsmechanismus zu sein. In der Oracle-Sprache sind Mutexe bekannt als Verriegelungen und Semaphoren sind bekannt als wartet auf .

Auf der untersten Ebene verwenden sie eine Art von atomaren testen und einstellen Mechanismus. Dieser liest den aktuellen Wert einer Speicherstelle, berechnet eine Art von Bedingung und schreibt einen Wert an dieser Stelle in einem einzigen Befehl aus, der kann nicht unterbrochen werden . Das bedeutet, dass Sie eine Mutex erwerben und testen können, ob jemand anderes sie vor Ihnen hatte.

Bei einer typischen Mutex-Implementierung führt ein Prozess oder Thread die Anweisung test-and-set aus und prüft, ob ein anderer Prozess den Mutex gesetzt hat. Ein wichtiger Punkt hierbei ist, dass es keine Interaktion mit dem Planer Wir haben also keine Ahnung (und es ist uns egal), wer das Schloss angebracht hat. Dann geben wir entweder unsere Zeitscheibe auf und versuchen es erneut, wenn die Aufgabe neu geplant wird, oder wir führen eine Spin-Lock . Ein Spinlock ist ein Algorithmus wie:

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

Wenn wir die Ausführung unseres geschützten Codes beendet haben (bekannt als kritischer Abschnitt ) setzen wir den Mutex-Wert einfach auf Null oder was auch immer 'clear' bedeutet. Wenn mehrere Aufgaben versuchen, die Mutex zu übernehmen, erhält die nächste Aufgabe, die zufällig nach der Freigabe der Mutex geplant wird, Zugriff auf die Ressource. Normalerweise verwendet man Mutexe, um eine synchronisierte Ressource zu kontrollieren, bei der der exklusive Zugriff nur für sehr kurze Zeiträume benötigt wird, normalerweise um eine gemeinsame Datenstruktur zu aktualisieren.

Ein Semaphor ist eine synchronisierte Datenstruktur (typischerweise unter Verwendung eines Mutex), die einen Zähler und einige Systemaufrufe enthält, die mit dem Scheduler etwas tiefer interagieren, als es die Mutex-Bibliotheken tun würden. Semaphoren werden inkrementiert und dekrementiert und verwendet, um Block Aufgaben, bis etwas anderes fertig ist. Siehe Erzeuger/Verbraucher-Problem für ein einfaches Beispiel dafür. Semaphore werden auf einen bestimmten Wert initialisiert - ein binäres Semaphor ist nur ein Spezialfall, bei dem das Semaphor auf 1 initialisiert wird. Ein Posting an eine Semaphore hat den Effekt, dass ein wartender Prozess aufgeweckt wird.

Ein grundlegender Semaphor-Algorithmus sieht folgendermaßen aus:

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

Im Falle eines binären Semaphors besteht der wichtigste praktische Unterschied zwischen den beiden in der Art der Systemdienste, die die eigentliche Datenstruktur umgeben.

EDIT: Wie evan richtig bemerkt hat, verlangsamen Spinlocks einen Einzelprozessorrechner. Sie würden ein Spinlock nur auf einem Multiprozessorrechner verwenden, da auf einem Einzelprozessor der Prozess, der die Mutex hält, diese niemals zurücksetzen wird, während eine andere Aufgabe läuft. Spinlocks sind nur auf Multiprozessor-Architekturen sinnvoll.

2 Stimmen

Ich glaube nicht, dass es üblich ist, dass ein Mutex mit Spinlocks implementiert wird. Auf einer Uni-proc-Maschine wäre dies absolut schrecklich für die Leistung.

0 Stimmen

Normalerweise würden Sie Spinlocks nur auf Multiprozessorsystemen verwenden.

0 Stimmen

Sogar unter SMP fällt man nach ein paar Spins zurück in den OS-unterstützten Schlaf/Wachzustand. (z.B. das Linux futex Systemaufruf existiert, um Mutex-/Semaphoren-Implementierungen mit niedriger Latenz im Benutzerraum zu unterstützen. de.wikipedia.org/wiki/Futex ) Auf dem schnellen Pfad ohne Beeinträchtigung oder wenn die Ressource bald verfügbar ist, haben Sie nie den Overhead eines Systemaufrufs. Aber man verbringt nicht mehr als ein paar Mikrosekunden mit Warten (Spinning). Die Einstellung der Parameter für Spin-Loop-Backoff und Wait ist natürlich von der Hardware und der Arbeitslast abhängig, aber die Standardbibliothek bietet in der Regel vernünftige Auswahlmöglichkeiten.

21voto

Praveen_Shukla Punkte 1194

Obwohl Mutex und Semaphoren als Synchronisationsprimitive verwendet werden, gibt es einen großen Unterschied zwischen ihnen. Im Falle eines Mutex kann nur der Thread, der den Mutex gesperrt oder erworben hat, diesen wieder entsperren. Im Falle einer Semaphore kann ein Thread, der auf eine Semaphore wartet, von einem anderen Thread signalisiert werden. Einige Betriebssysteme unterstützen die Verwendung von Mutex und Semaphoren zwischen Prozessen. Typischerweise wird die Verwendung im gemeinsamen Speicher erstellt.

0 Stimmen

"kann von einem anderen Thread signalisiert werden", was bedeutet das, geben Sie ein Beispiel.

20voto

Sumit Naik Punkte 674

Mutex: Angenommen, wir haben einen kritischen Abschnitt, auf den Thread T1 zugreifen möchte, dann folgt er den folgenden Schritten. T1:

  1. Schloss
  2. Kritischen Abschnitt verwenden
  3. freischalten

Binäres Semaphor: Es funktioniert auf der Grundlage der Signalisierung von wait und signal. wait(s) verringert den Wert von "s" um eins, normalerweise wird der Wert von "s" mit dem Wert "1" initialisiert, signal(s) erhöht den "s"-Wert um eins. Wenn der "s"-Wert 1 ist, bedeutet das, dass niemand den kritischen Abschnitt benutzt, wenn der Wert 0 ist, bedeutet das, dass der kritische Abschnitt in Gebrauch ist. Angenommen, der Thread T2 verwendet den kritischen Abschnitt, dann folgt er den folgenden Schritten. T2 :

  1. wait(s)//anfänglich ist der Wert von s gleich eins, nach dem Aufruf von wait wird der Wert um eins, d.h. 0, verringert
  2. Kritischen Abschnitt verwenden
  3. signal(s) // jetzt wird der Wert von s erhöht und zu 1

Der Hauptunterschied zwischen Mutex und Binary Semaphore besteht darin, dass in Mutext, wenn ein Thread den kritischen Abschnitt sperrt, er den kritischen Abschnitt entsperren muss und kein anderer Thread ihn entsperren kann, aber im Falle von Binary Semaphore, wenn ein Thread den kritischen Abschnitt mit der wait(s)-Funktion sperrt, wird der Wert von s "0" und niemand kann darauf zugreifen, bis der Wert von "s" 1 wird. Daher hat ein binärer Semaphor-Thread kein Eigentumsrecht.

12voto

Unter Windows gibt es zwei Unterschiede zwischen Mutexen und binären Semaphoren:

  1. Ein Mutex kann nur von dem Thread freigegeben werden, der Eigentümer ist, d. h. von dem Thread, der zuvor die Wait-Funktion aufgerufen hat (oder der bei der Erstellung des Mutex Eigentümer wurde). Eine Semaphore kann von jedem Thread freigegeben werden.

  2. Ein Thread kann eine Wait-Funktion wiederholt auf einem Mutex aufrufen, ohne zu blockieren. Wenn Sie jedoch eine Wait-Funktion zweimal auf einem binären Semaphor aufrufen, ohne den Semaphor dazwischen freizugeben, wird der Thread blockiert.

6 Stimmen

Gute Antwort. In #2 beschreiben Sie einen rekursiven Mutex - nicht alle Mutexe sind notwendigerweise rekursiv. Z.B., cs.wustl.edu/~schmidt/ACE.FAQ.html#Q14

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X