Wann sollten wir Mutex verwenden und wann sollten wir Semaphor verwenden

Antworten:

92

So erinnere ich mich, wann ich was verwenden soll -

Semaphor: Verwenden Sie ein Semaphor, wenn Sie (Thread) schlafen möchten, bis ein anderer Thread Sie auffordert, aufzuwachen. Das Semaphor 'down' tritt in einem Thread (Produzent) und das Semaphor 'up' (für dasselbe Semaphor) in einem anderen Thread (Consumer) auf. Beispiel: Bei Producer-Consumer-Problemen möchte der Produzent schlafen, bis mindestens ein Pufferschlitz leer ist - nur Der Consumer-Thread kann erkennen, wann ein Puffersteckplatz leer ist.

Mutex: Verwenden Sie einen Mutex, wenn Sie (Thread) Code ausführen möchten, der nicht gleichzeitig von einem anderen Thread ausgeführt werden soll. Mutex 'down' kommt in einem Thread vor und Mutex 'up' muss später im selben Thread vorkommen. Beispiel: Wenn Sie einen Knoten aus einer globalen verknüpften Liste löschen, möchten Sie nicht, dass ein anderer Thread beim Löschen des Knotens mit Zeigern herumfummelt. Wenn Sie einen Mutex erwerben und gerade einen Knoten löschen und ein anderer Thread versucht, denselben Mutex abzurufen, wird dieser in den Ruhezustand versetzt, bis Sie den Mutex freigeben.

Spinlock: Verwenden Sie einen Spinlock, wenn Sie wirklich einen Mutex verwenden möchten, Ihr Thread jedoch nicht schlafen darf. Beispiel: Ein Interrupt-Handler im OS-Kernel darf niemals schlafen. In diesem Fall friert das System ein / stürzt ab. Wenn Sie vom Interrupt-Handler einen Knoten in eine global freigegebene verknüpfte Liste einfügen müssen, erwerben Sie einen Spinlock - Knoten einfügen - Spinlock freigeben.

Annu Gogatya
quelle
1
Hinzufügen zu: Semaphoren und der Mutex sind zwei Möglichkeiten, um eine Synchronisation bereitzustellen. Semaphor kann eher mit der Signalisierung zusammenhängen (z. B. Problem mit Produzenten und Verbrauchern), und Mutex kann eher mit der Ermöglichung des Zugriffs auf eine nach der anderen zusammenhängen (mehrere Anforderungen für den Zugriff auf gemeinsam genutzte Ressourcen, jedoch jeweils nur eine). [schöner Artikel: geeksforgeeks.org/mutex-vs-semaphore/]
Parasrish
57

Ein Mutex ist ein Objekt zum gegenseitigen Ausschluss, ähnlich einem Semaphor, das jedoch jeweils nur ein Schließfach zulässt und dessen Eigentumsbeschränkungen möglicherweise strenger sind als ein Semaphor.

Es kann als äquivalent zu einem normalen Zählsemaphor (mit einer Zählung von eins) und der Anforderung angesehen werden, dass es nur von demselben Thread freigegeben werden kann, der es gesperrt hat (a) .

Ein Semaphor hingegen hat eine beliebige Anzahl und kann von so vielen Schließfächern gleichzeitig gesperrt werden. Und es kann nicht erforderlich sein, dass es von demselben Thread veröffentlicht wird, der es beansprucht hat (aber wenn nicht, müssen Sie sorgfältig verfolgen, wer derzeit dafür verantwortlich ist, ähnlich wie der zugewiesene Speicher).

Wenn Sie also mehrere Instanzen einer Ressource haben (z. B. drei Bandlaufwerke), können Sie ein Semaphor mit einer Anzahl von 3 verwenden. Beachten Sie, dass dies Ihnen nicht sagt, welches dieser Bandlaufwerke Sie haben, sondern nur, dass Sie haben eine bestimmte Anzahl.

Auch mit Semaphoren ist es möglich, dass ein einzelnes Schließfach mehrere Instanzen einer Ressource sperrt, z. B. für eine Band-zu-Band-Kopie. Wenn Sie über eine Ressource verfügen (z. B. einen Speicherort, den Sie nicht beschädigen möchten), ist ein Mutex besser geeignet.

Äquivalente Operationen sind:

Counting semaphore          Mutual exclusion semaphore
--------------------------  --------------------------
  Claim/decrease (P)                  Lock
  Release/increase (V)                Unlock

Nebenbei: Falls Sie sich jemals über die bizarren Buchstaben gewundert haben, mit denen Semaphoren beansprucht und veröffentlicht wurden, liegt dies daran, dass der Erfinder Niederländer war. Probeer te verlagen bedeutet zu versuchen, abzunehmen, während verhogen zu erhöhen bedeutet.


(a) ... oder es kann als etwas völlig anderes als ein Semaphor angesehen werden, das aufgrund seiner fast immer unterschiedlichen Verwendung sicherer sein kann.

paxdiablo
quelle
Okay, ich bin auch auf binäres Semaphor gestoßen. Wann sollten wir uns für ein binäres Semaphor entscheiden müssen und wann sollten wir Mutex verwenden?
Karthik Balaguru
Konzeptionell ist ein binärer Semaphor ist ein Mutex, und es ist äquivalent zu einem normalen Semaphor mit einem Ein-Count. Es kann Unterschiede in der Implementierung des Konzepts geben, wie z. B. Effizienz oder Besitz der Ressource (kann von einer anderen Person als dem Antragsteller freigegeben werden, was ich übrigens nicht zustimme - eine Ressource sollte nur von dem Thread freigegeben werden können, der sie beansprucht hat ).
Paxdiablo
1
Ein weiterer möglicher Implementierungsunterschied ist der rekursive Mutex. Da es nur eine Ressource gibt, kann ein einzelner Thread diese möglicherweise mehrmals sperren (sofern er sie auch so oft freigibt). Dies ist mit einer Ressource mit mehreren Instanzen nicht so einfach, da Sie möglicherweise nicht wissen, ob der Thread eine andere Instanz oder dieselbe Instanz erneut beanspruchen möchte .
Paxdiablo
1
Sie lösen ein bestimmtes Problem. Die Tatsache, dass das Problem, das sie lösen, Menschen sind, die Mutexe nicht ganz verstehen, sollte die Lösung in keiner Weise
herabsetzen
5
Ein Mutex unterscheidet sich grundlegend von einem binären Semaphor. Entschuldigung, aber diese Definition ist falsch
Peer Stritzinger
49

Es ist sehr wichtig zu verstehen, dass ein Mutex kein Semaphor mit Zählung 1 ist!

Dies ist der Grund, warum es Dinge wie binäre Semaphoren gibt (die wirklich Semaphoren mit Zählung 1 sind).

Der Unterschied zwischen einem Mutex und einem Binärsemaphor ist das Prinzip des Eigentums:

Ein Mutex wird von einer Aufgabe erfasst und muss daher auch von derselben Aufgabe freigegeben werden. Dies ermöglicht es, mehrere Probleme mit binären Semaphoren zu beheben (versehentliche Freigabe, rekursiver Deadlock und Prioritätsinversion).

Vorsichtsmaßnahme: Ich schrieb "macht es möglich", ob und wie diese Probleme behoben werden, hängt von der Implementierung des Betriebssystems ab.

Da der Mutex von derselben Aufgabe freigegeben werden muss, ist er für die Synchronisierung von Aufgaben nicht sehr gut. In Kombination mit Bedingungsvariablen erhalten Sie jedoch sehr leistungsfähige Bausteine ​​zum Erstellen aller Arten von IPC-Grundelementen.

Meine Empfehlung lautet also: Wenn Sie Mutexe und Bedingungsvariablen (wie bei POSIX-Pthreads) sauber implementiert haben, verwenden Sie diese.

Verwenden Sie Semaphore nur, wenn sie genau zu dem Problem passen, das Sie lösen möchten. Versuchen Sie nicht, andere Grundelemente zu erstellen (z. B. rw-Sperren aus Semaphoren, verwenden Sie Mutexe und Bedingungsvariablen für diese).

Es gibt viele Missverständnisse bei Mutexen und Semaphoren. Die beste Erklärung, die ich bisher gefunden habe, ist in diesem dreiteiligen Artikel:

Mutex vs. Semaphoren - Teil 1: Semaphoren

Mutex vs. Semaphoren - Teil 2: Der Mutex

Mutex vs. Semaphoren - Teil 3 (letzter Teil): Probleme des gegenseitigen Ausschlusses

Peer Stritzinger
quelle
Die URLs zu dieser Seite enthalten funky Charaktere und funktionieren daher nicht ... Ich arbeite daran
Peer Stritzinger
13

Obwohl die Antwort von @opaxdiablo völlig korrekt ist, möchte ich darauf hinweisen, dass das Verwendungsszenario beider Dinge sehr unterschiedlich ist. Der Mutex wird verwendet, um Teile des Codes vor der gleichzeitigen Ausführung zu schützen. Semaphoren werden für einen Thread verwendet, um die Ausführung eines anderen Threads zu signalisieren.

/* Task 1 */
pthread_mutex_lock(mutex_thing);
    // Safely use shared resource
pthread_mutex_unlock(mutex_thing);



/* Task 2 */
pthread_mutex_lock(mutex_thing);
   // Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex

Das Semaphorszenario ist anders:

/* Task 1 - Producer */
sema_post(&sem);   // Send the signal

/* Task 2 - Consumer */
sema_wait(&sem);   // Wait for signal

Weitere Erläuterungen finden Sie unter http://www.netrino.com/node/202

Patrick Schlüter
quelle
2
Du hast recht. Selbst wenn Sie ein Semaphor mit einer Anzahl von eins verwenden, implizieren Sie etwas über das, was Sie tun, als wenn Sie einen Mutex verwenden.
Omnifarious
Ich bin mir nicht sicher, ob ich damit einverstanden bin, obwohl ich nicht so vehement anderer Meinung bin, dass ich Sie ablehnen werde :-) Sie sagen, dass das Verwendungsmuster von Semaphoren darin besteht, Threads zu benachrichtigen, aber genau das tun Mutexe, wenn ein anderer Thread wartet drauf und genau das, was Semaphoren nicht tun, wenn es keine Threads gibt sema_wait:-) Meiner Meinung nach geht es sowohl um Ressourcen als auch um die Benachrichtigung, die an andere Threads weitergegeben wird, ist ein Nebeneffekt (sehr wichtig, leistungsmäßig) der Schutz.
Paxdiablo
You say that the usage pattern of semaphores is to notify threadsEin Punkt zum Benachrichtigen von Threads. Sie können anrufen sem_postaus einem Signal - Handler sicher ( pubs.opengroup.org/onlinepubs/009695399/functions/... ) , aber es ist nicht auf Anruf empfohlen pthread_mutex_lockund pthread_mutex_unlockvon Signal - Handler ( manpages.ubuntu.com/manpages/lucid/man3/... )
@paxdiablo: Es gibt einen Hauptunterschied zwischen diesem binären Mutex-Semaphor, der darin besteht, die Referenzanzahl beizubehalten. Mutex oder Sie können sagen, dass ein bedingter Mutex keine Zählung im Zusammenhang mit der Sperre beibehält, wenn sempahore verwendet wird, um die Zählung aufrechtzuerhalten. Sem_wait und sem_post behalten also die Zählung bei.
Prak
9

Siehe "Das Toilettenbeispiel" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :

Mutex:

Ist ein Schlüssel zu einer Toilette. Eine Person kann den Schlüssel haben - die Toilette besetzen - zu der Zeit. Wenn Sie fertig sind, gibt die Person den Schlüssel an die nächste Person in der Warteschlange weiter (gibt ihn frei).

Offiziell: "Mutexe werden normalerweise verwendet, um den Zugriff auf einen Abschnitt des wiedereintretenden Codes zu serialisieren, der nicht gleichzeitig von mehr als einem Thread ausgeführt werden kann. Ein Mutex-Objekt erlaubt nur einen Thread in einen kontrollierten Abschnitt, wodurch andere Threads gezwungen werden, auf die zugegriffen werden soll diesen Abschnitt, um zu warten, bis der erste Thread diesen Abschnitt verlassen hat. " Ref: Symbian Developer Library

(Ein Mutex ist wirklich ein Semaphor mit dem Wert 1.)

Semaphor:

Ist die Anzahl der freien identischen Toilettenschlüssel. Nehmen wir zum Beispiel an, wir haben vier Toiletten mit identischen Schlössern und Schlüsseln. Die Anzahl der Semaphore - die Anzahl der Schlüssel - wird zu Beginn auf 4 gesetzt (alle vier Toiletten sind frei), und der Zählwert wird verringert, wenn Personen hereinkommen. Wenn alle Toiletten voll sind, d. H. Es sind keine freien Schlüssel mehr vorhanden. Die Anzahl der Semaphore beträgt 0. Wenn nun Gl. Eine Person verlässt die Toilette, das Semaphor wird auf 1 (ein freier Schlüssel) erhöht und der nächsten Person in der Warteschlange übergeben.

Offiziell: "Ein Semaphor beschränkt die Anzahl der gleichzeitigen Benutzer einer gemeinsam genutzten Ressource auf eine maximale Anzahl. Threads können den Zugriff auf die Ressource anfordern (Dekrementieren des Semaphors) und signalisieren, dass sie die Ressource nicht mehr verwenden (Inkrementieren des Semaphors). "" Ref: Symbian Developer Library

Fornwall
quelle
7

Ich versuche nicht verrückt zu klingen, kann mir aber nicht helfen.

Ihre Frage sollte sein, was der Unterschied zwischen Mutex und Semaphoren ist. Genauer gesagt sollte die Frage lauten: Wie ist die Beziehung zwischen Mutex und Semaphoren?

(Ich hätte diese Frage hinzugefügt, bin mir aber hundertprozentig sicher, dass ein übereifriger Moderator sie als Duplikat schließen würde, ohne den Unterschied zwischen Unterschied und Beziehung zu verstehen.)

In der Objektterminologie können wir Folgendes beobachten:

Beobachtung.1 Semaphor enthält Mutex

Beobachtung.2 Mutex ist kein Semaphor und Semaphor ist kein Mutex.

Es gibt einige Semaphore, die so tun, als wären sie Mutex, sogenannte binäre Semaphoren, aber sie flippen NICHT Mutex aus.

Es gibt eine spezielle Zutat namens Signaling (posix verwendet condition_variable für diesen Namen), die erforderlich ist, um aus Mutex ein Semaphor zu machen. Betrachten Sie es als Benachrichtigungsquelle. Wenn zwei oder mehr Threads dieselbe Benachrichtigungsquelle abonniert haben, ist es möglich, diese Nachricht entweder an EINEN oder an ALLE zu senden, um sie zu aktivieren.

Mit Semaphoren können ein oder mehrere Zähler verknüpft sein, die durch Mutex geschützt sind. Das einfachste Szenario für Semaphore ist, dass es einen einzelnen Zähler gibt, der entweder 0 oder 1 sein kann.

Hier strömt Verwirrung wie Monsunregen herein.

Ein Semaphor mit einem Zähler, der 0 oder 1 sein kann, ist KEIN Mutex.

Mutex hat zwei Zustände (0,1) und einen Besitz (Aufgabe). Semaphor hat einen Mutex, einige Zähler und eine Bedingungsvariable.

Verwenden Sie jetzt Ihre Vorstellungskraft, und jede Kombination aus Verwendung des Zählers und dem Zeitpunkt des Signals kann eine Art Semaphor ergeben.

  1. Einzelner Zähler mit dem Wert 0 oder 1 und Signalisierung, wenn der Wert auf 1 geht UND dann einen der auf das Signal wartenden Typen entsperrt == Binäres Semaphor

  2. Einzelner Zähler mit dem Wert 0 bis N und Signalisierung, wenn der Wert kleiner als N ist, und Sperren / Warten, wenn der Wert N ist == Zählsemaphor

  3. Einzelner Zähler mit dem Wert 0 bis N und Signalisierung, wenn der Wert auf N geht, und Sperren / Warten, wenn der Wert kleiner als N == Barrieresemaphor ist (nun, wenn sie ihn nicht aufrufen, sollten sie es tun.)

Nun zu Ihrer Frage, wann was zu verwenden ist. (ODER eher die korrekte Frage Version 3, wann Mutex und wann Binärsemaphor verwendet werden soll, da es keinen Vergleich mit Nicht-Binärsemaphor gibt.) Verwenden Sie Mutex, wenn 1. Sie ein benutzerdefiniertes Verhalten wünschen, das nicht von Binär bereitgestellt wird Semaphor, wie Spin-Lock oder Fast-Lock oder rekursive Sperren. Normalerweise können Sie Mutexe mit Attributen anpassen, aber das Anpassen von Semaphoren ist nichts anderes als das Schreiben eines neuen Semaphors. 2. Sie möchten ein leichtes oder schnelleres Grundelement

Verwenden Sie Semaphoren, wenn genau das, was Sie wollen, von ihnen bereitgestellt wird.

Wenn Sie nicht verstehen, was Ihre Implementierung von Binärsemaphor bietet, verwenden Sie meiner Meinung nach Mutex.

Und zum Schluss lesen Sie ein Buch, anstatt sich nur auf SO zu verlassen.

Ajeet Ganga
quelle
5

Ich denke, die Frage sollte der Unterschied zwischen Mutex und binärem Semaphor sein.

Mutex = Es handelt sich um einen Besitzersperrmechanismus. Nur der Thread, der die Sperre erwirbt, kann die Sperre aufheben.

binäres Semaphor = Es ist eher ein Signalmechanismus, jeder andere Thread mit höherer Priorität kann, wenn gewünscht, signalisieren und die Sperre übernehmen.

Saurabh Sengar
quelle
5

Mutex dient zum Schutz der gemeinsam genutzten Ressource.
Semaphor soll die Fäden versenden.

Mutex:
Stellen Sie sich vor, es gibt einige Tickets zu verkaufen. Wir können einen Fall simulieren, in dem viele Leute die Tickets gleichzeitig kaufen: Jede Person ist ein Thread, um Tickets zu kaufen. Natürlich müssen wir den Mutex verwenden, um die Tickets zu schützen, da es sich um die gemeinsam genutzte Ressource handelt.


Semaphor:
Stellen Sie sich vor, wir müssen eine Berechnung wie folgt durchführen:

c = a + b;

Außerdem benötigen wir eine Funktion geta()zum Berechnen a, eine Funktion getb()zum Berechnen bund eine Funktion getc()zum Berechnen c = a + b.

Natürlich können wir nicht tun , das c = a + bes sei denn , geta()und getb()beendet worden sind .
Wenn die drei Funktionen drei Threads sind, müssen wir die drei Threads versenden.

int a, b, c;
void geta()
{
    a = calculatea();
    semaphore_increase();
}

void getb()
{
    b = calculateb();
    semaphore_increase();
}

void getc()
{
    semaphore_decrease();
    semaphore_decrease();
    c = a + b;
}

t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);

Mit Hilfe des Semaphors kann der obige Code sicherstellen, dass er t3seine Arbeit erst dann erledigt, wenn t1undt2 hat ihre Arbeit getan.

Mit einem Wort, Semaphor soll Threads als logische Reihenfolge ausführen lassen, während Mutex die gemeinsam genutzte Ressource schützen soll.
Sie sind also NICHT dasselbe, auch wenn manche Leute immer sagen, dass Mutex ein spezielles Semaphor mit dem Anfangswert 1 ist. Sie können dies auch so sagen, aber bitte beachten Sie, dass sie in verschiedenen Fällen verwendet werden. Ersetzen Sie nicht eins durch das andere, auch wenn Sie das können.

Yves
quelle
Der Verkauf von Tickets ist ein gutes Beispiel. Semaphor Beispiel ist etwas unklar (für mich sowieso).
Prayagupd
1
@prayagupd Semaphore-Beispiel ist das Erstellen von Threads in einer bestimmten Reihenfolge, während für den Verkauf von Tickets keine Bestellung erforderlich ist. Wenn es drei Personen gibt: a, b und c. Wenn sie Tickets kaufen, ist es uns egal, in welcher Reihenfolge sie Tickets kaufen. Wenn wir jedoch eine solche Berechnung zu tun: x = getx(); y = gety(); z = x + y;Aus irgendeinem Grund verwenden wir drei Themen , die drei Dinge zu tun, jetzt die Reihenfolge der Themen ist sehr wichtig , weil wir nicht tun können , x + yes sei denn , getxund getyfertig. Mit einem Wort, Semaphor wird verwendet, wenn wir uns um die Reihenfolge der Ausführung von Multithreading kümmern.
Yves
hab dich. Es klingt ähnlich wie Barriere . Ich kann sagen, dass warten, bis Threads xund abgeschlossen ysind, dann berechnen z = x + y. Ich weiß, Java hat CyclicBarrier. Ich bin mir auch nicht sicher, ob ich sagen kann, dass mapreduceSemaphor auch verwendet wird, weil ich es nicht kann, reducebis alle maps abgeschlossen sind.
Prayagupd
@prayagupd Ja. Das kannst du sagen.
Yves
2

Alle oben genannten Antworten sind von guter Qualität, aber dies ist nur zum Auswendiglernen. Der Name Mutex leitet sich von " Gegenseitig ausschließend" ab. Daher sind Sie motiviert, sich eine Mutex-Sperre als gegenseitigen Ausschluss zwischen zwei wie in jeweils nur einem vorzustellen, und wenn ich besaß es kann man erst haben, nachdem ich es freigegeben habe. Andererseits existiert ein solcher Fall für Semaphore nicht wie ein Verkehrssignal (was das Wort Semaphore auch bedeutet).

Nishant Sondhi
quelle
1

Wie bereits erwähnt, ist ein Semaphor mit einer Zählung von eins dasselbe wie ein 'binäres' Semaphor, das dasselbe wie ein Mutex ist.

Die wichtigsten Dinge, die ich gesehen habe, sind Semaphoren mit einer größeren Anzahl als einer, für die verwendet wird, Produzenten / Konsumenten-Situationen, in denen Sie eine Warteschlange mit einer bestimmten festen Größe haben.

Sie haben dann zwei Semaphoren. Das erste Semaphor wird anfänglich auf die Anzahl der Elemente in der Warteschlange gesetzt, und das zweite Semaphor wird auf 0 gesetzt. Der Produzent führt eine P-Operation für das erste Semaphor aus und fügt es der Warteschlange hinzu. und führt eine V-Operation auf der zweiten aus. Der Verbraucher führt eine P-Operation für das zweite Semaphor aus, entfernt sie aus der Warteschlange und führt dann eine V-Operation für das erste aus.

Auf diese Weise wird der Produzent blockiert, wenn er die Warteschlange füllt, und der Verbraucher wird blockiert, wenn die Warteschlange leer ist.

Allgegenwärtig
quelle
1

Ein Mutex ist ein Sonderfall eines Semaphors. Ein Semaphor ermöglicht es mehreren Threads, in den kritischen Abschnitt zu gelangen. Beim Erstellen eines Semaphors definieren Sie, wie Threads im kritischen Abschnitt zulässig sein dürfen. Natürlich muss Ihr Code mehrere Zugriffe auf diesen kritischen Abschnitt verarbeiten können.

Frode Akselsen
quelle
-1

Binäres Semaphor und Mutex sind unterschiedlich. Aus Sicht des Betriebssystems werden ein binäres Semaphor und ein Zählsemaphor auf die gleiche Weise implementiert, und ein binäres Semaphor kann den Wert 0 oder 1 haben.

Mutex -> Kann nur für einen einzigen Zweck des gegenseitigen Ausschlusses für einen kritischen Codeabschnitt verwendet werden.

Semaphor -> Kann zur Lösung verschiedener Probleme verwendet werden. Ein binäres Semaphor kann zur Signalisierung verwendet werden und auch das Problem des gegenseitigen Ausschlusses lösen. Wenn es auf 0 initialisiert wird , löst es das Signalisierungsproblem und wenn es auf 1 initialisiert wird , löst es das Problem des gegenseitigen Ausschlusses .

Wenn die Anzahl der Ressourcen größer ist und synchronisiert werden muss, können wir das Zählsemaphor verwenden.

In meinem Blog habe ich diese Themen ausführlich besprochen.

https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html

Lumpen
quelle