Ich habe diese Wörter im Zusammenhang mit der gleichzeitigen Programmierung gehört, aber was ist der Unterschied zwischen ihnen?
concurrency
locking
mutex
semaphore
Sieger
quelle
quelle
Antworten:
Durch eine Sperre kann nur ein Thread in das gesperrte Teil eintreten, und die Sperre wird nicht für andere Prozesse freigegeben.
Ein Mutex ist dasselbe wie eine Sperre, kann jedoch systemweit sein (von mehreren Prozessen gemeinsam genutzt).
Ein Semaphor macht dasselbe wie ein Mutex, erlaubt jedoch die Eingabe von x Threads. Dies kann beispielsweise verwendet werden, um die Anzahl der gleichzeitig ausgeführten CPU-, Io- oder RAM-intensiven Tasks zu begrenzen.
Einen ausführlicheren Beitrag über die Unterschiede zwischen Mutex und Semaphor finden Sie hier .
Sie haben auch Lese- / Schreibsperren, die entweder eine unbegrenzte Anzahl von Lesern oder 1 Schreiber gleichzeitig zulassen.
quelle
Es gibt viele Missverständnisse in Bezug auf diese Wörter.
Dies ist aus einem früheren Beitrag ( https://stackoverflow.com/a/24582076/3163691 ), der hier hervorragend passt:
1) Kritischer Abschnitt = Benutzerobjekt, mit dem nur ein aktiver Thread von vielen anderen innerhalb eines Prozesses ausgeführt werden kann . Die anderen nicht ausgewählten Threads (@, die dieses Objekt erfassen) werden in den Ruhezustand versetzt .
[Keine Interprozessfähigkeit, sehr primitives Objekt].
2) Mutex-Semaphor (auch bekannt als Mutex) = Kernel-Objekt, mit dem nur ein aktiver Thread von vielen anderen unter verschiedenen Prozessen ausgeführt werden kann . Die anderen nicht ausgewählten Threads (@, die dieses Objekt erfassen) werden in den Ruhezustand versetzt . Dieses Objekt unterstützt Thread-Besitz, Benachrichtigung über die Beendigung des Threads, Rekursion (mehrere Aufrufe von demselben Thread abrufen) und Vermeidung von Prioritätsumkehrungen.
[Interprozessfähigkeit, sehr sicher zu bedienen, eine Art Synchronisationsobjekt auf hoher Ebene].
3) Counting Semaphore (auch bekannt als Semaphore) = Kernel-Objekt, mit dem eine Gruppe aktiver Threads von vielen anderen ausgeführt werden kann. Die anderen nicht ausgewählten Threads (@, die dieses Objekt erfassen) werden in den Ruhezustand versetzt .
[Die Interprozessfähigkeit ist jedoch nicht sehr sicher zu verwenden, da die folgenden 'Mutex'-Attribute fehlen: Benachrichtigung über Thread-Beendigung, Rekursion?,' Vermeidung von Prioritätsumkehrungen 'usw.].
4) Und jetzt, wenn wir über 'Spinlocks' sprechen, zuerst einige Definitionen:
Kritischer Bereich = Ein Speicherbereich, der von zwei oder mehr Prozessen gemeinsam genutzt wird.
Lock = Eine Variable, deren Wert den Zugang zu einem 'kritischen Bereich' erlaubt oder verweigert. (Es könnte als einfaches 'Boolesches Flag' implementiert werden).
Besetztes Warten = Kontinuierliches Testen einer Variablen, bis ein Wert angezeigt wird.
Schließlich:
Spin-Lock (auch bekannt als Spinlock) = Eine Sperre, bei der viel gewartet wird . (Der Erwerb der Sperre erfolgt durch xchg oder ähnliche atomare Operationen ).
[Kein Thread schlafen, meistens nur auf Kernel-Ebene verwendet. Ineffizient für Code auf Benutzerebene].
Als letzten Kommentar bin ich mir nicht sicher, aber ich kann wetten, dass die oben genannten ersten 3 Synchronisierungsobjekte (Nr. 1, Nr. 2 und Nr. 3) dieses einfache Biest (Nr. 4) als Teil ihrer Implementierung verwenden.
Haben Sie einen guten Tag!.
Verweise:
-Real-Time-Konzepte für eingebettete Systeme von Qing Li mit Caroline Yao (CMP Books).
-Moderne Betriebssysteme (3.) von Andrew Tanenbaum (Pearson Education International).
-Programmieranwendungen für Microsoft Windows (4.) von Jeffrey Richter (Microsoft Programming Series).
Sie können auch einen Blick darauf werfen: https://stackoverflow.com/a/24586803/3163691
quelle
Die meisten Probleme können mit (i) nur Sperren, (ii) nur Semaphoren, ... oder (iii) einer Kombination aus beiden gelöst werden! Wie Sie vielleicht festgestellt haben, sind sie sich sehr ähnlich: Beide verhindern Rennbedingungen , beide haben
acquire()
/release()
Operationen, beide führen dazu, dass null oder mehr Threads blockiert / vermutet werden ... Der entscheidende Unterschied liegt wirklich nur darin, wie sie sperren und entsperren .Bei beiden Sperren / Semaphoren wird beim Versuch, einen Aufruf durchzuführen,
acquire()
während sich das Grundelement im Status 0 befindet, der aufrufende Thread angehalten. Für Sperren - Versuche, die Sperre im Status 1 zu erhalten, sind erfolgreich. Für Semaphore - Versuche, die Sperre in den Zuständen {1, 2, 3, ...} zu erlangen, sind erfolgreich.Wenn für Sperren im Status 0 derselbe Thread, der zuvor aufgerufen wurde
acquire()
, jetzt die Freigabe aufruft, ist die Freigabe erfolgreich. Wenn ein anderer Thread dies versucht hat, liegt es an der Implementierung / Bibliothek, was passiert (normalerweise wird der Versuch ignoriert oder ein Fehler wird ausgelöst). Bei Semaphoren im Status 0 kann jeder Thread die Freigabe aufrufen und ist erfolgreich (unabhängig davon, welcher Thread zuvor verwendet wurde, um das Semaphor in den Status 0 zu versetzen).Aus der vorangegangenen Diskussion können wir ersehen, dass Sperren den Begriff eines Besitzers haben (der einzige Thread, der die Freigabe aufrufen kann, ist der Eigentümer), während Semaphoren keinen Eigentümer haben (jeder Thread kann die Freigabe eines Semaphors aufrufen).
Was viel Verwirrung stiftet, ist, dass es sich in der Praxis um viele Variationen dieser Definition auf hoher Ebene handelt.
Wichtige zu berücksichtigende Variationen :
acquire()
/release()
genannt werden? - [Variiert massiv ]Dies hängt von Ihrem Buch / Dozenten / Sprache / Bibliothek / Umgebung ab.
Hier ist eine kurze Tour, in der erläutert wird, wie einige Sprachen diese Details beantworten.
C, C ++ ( Pthreads )
pthread_mutex_t
. Standardmäßig können sie nicht mit anderen Prozessen (PTHREAD_PROCESS_PRIVATE
) geteilt werden, Mutex haben jedoch ein Attribut namens pshared . Wenn festgelegt, wird der Mutex von Prozessen geteilt (PTHREAD_PROCESS_SHARED
).sem_t
. Ähnlich wie bei Mutexen können Semaphoren von mehreren Prozessen gemeinsam genutzt oder für die Threads eines einzelnen Prozesses privat gehalten werden. Dies hängt vom angegebenen Argument pshared absem_init
.Python ( threading.py )
threading.RLock
) ist meistens dasselbe wie C / C ++pthread_mutex_t
s. Beide sind wiedereintrittsfähig . Dies bedeutet, dass sie möglicherweise nur von demselben Thread entsperrt werden, der sie gesperrt hat. Es ist der Fall, dasssem_t
Semaphoren,threading.Semaphore
Semaphoren undtheading.Lock
Sperren nicht wiedereintrittsfähig sind - denn es ist der Fall, dass jeder Thread das Sperren / Sperren des Semaphors durchführen kann.threading.Semaphore
) ist meistens dasselbe wiesem_t
. Obwohl mitsem_t
, wird eine Warteschlange mit Thread-IDs verwendet, um die Reihenfolge zu speichern, in der Threads blockiert wurden, als versucht wurde, sie zu sperren, während sie gesperrt sind. Wenn ein Thread ein Semaphor entsperrt, wird der erste Thread in der Warteschlange (falls vorhanden) als neuer Eigentümer ausgewählt. Die Thread-ID wird aus der Warteschlange entfernt und das Semaphor wird wieder gesperrt. Bei wird jedochthreading.Semaphore
ein Satz anstelle einer Warteschlange verwendet, sodass die Reihenfolge, in der Threads blockiert wurden, nicht gespeichert wird. Jeder Thread im Satz kann als nächster Eigentümer ausgewählt werden.Java ( java.util.concurrent )
java.util.concurrent.ReentrantLock
) ist größtenteils dasselbe wie das von C / C ++pthread_mutex_t
und das von Python,threading.RLock
da es auch eine wiedereintrittssperre implementiert. Das Teilen von Sperren zwischen Prozessen ist in Java schwieriger, da die JVM als Vermittler fungiert. Wenn ein Thread versucht, eine Sperre zu entsperren, die er nicht besitzt, wird eineIllegalMonitorStateException
ausgelöst.java.util.concurrent.Semaphore
) ist meistens dasselbe wiesem_t
undthreading.Semaphore
. Der Konstruktor für Java-Semaphoren akzeptiert einen booleschen Fairness- Parameter, der steuert, ob ein Satz (false) oder eine Warteschlange (true) zum Speichern der wartenden Threads verwendet werden soll.In der Theorie werden Semaphoren oft diskutiert, in der Praxis werden Semaphoren jedoch nicht so häufig verwendet. Ein Semaphor enthält nur den Status einer Ganzzahl, daher ist es oft ziemlich unflexibel und viele werden gleichzeitig benötigt - was zu Schwierigkeiten beim Verständnis von Code führt. Auch die Tatsache, dass jeder Thread ein Semaphor freigeben kann, ist manchmal unerwünscht. Stattdessen werden objektorientiertere / übergeordnete Synchronisationsprimitive / -abstraktionen wie "Bedingungsvariablen" und "Monitore" verwendet.
quelle
Schauen Sie sich das Multithreading-Tutorial von John Kopplin an.
Im Abschnitt Synchronisation zwischen Threads erklärt er die Unterschiede zwischen Ereignis, Sperre, Mutex, Semaphor und wartbarem Timer
quelle
Ich werde versuchen, es mit Beispielen zu behandeln:
Sperren: Ein Beispiel, das Sie verwenden würden,
lock
wäre ein freigegebenes Wörterbuch, in das Elemente (die eindeutige Schlüssel haben müssen) hinzugefügt werden.Die Sperre würde sicherstellen, dass ein Thread nicht den Code-Mechanismus eingibt, der prüft, ob sich ein Element im Wörterbuch befindet, während ein anderer Thread (der sich im kritischen Abschnitt befindet) diese Prüfung bereits bestanden hat und das Element hinzufügt. Wenn ein anderer Thread versucht, einen gesperrten Code einzugeben, wartet er (wird blockiert), bis das Objekt freigegeben wird.
Semaphor: Angenommen, Sie haben einen Pool von Verbindungen. Dann kann ein einzelner Thread ein Element im Pool reservieren, indem er darauf wartet, dass das Semaphor eine Verbindung erhält. Anschließend wird die Verbindung verwendet, und wenn die Arbeit erledigt ist, wird die Verbindung durch Freigeben des Semaphors freigegeben.
Das Codebeispiel, das ich liebe, ist eines der Türsteher von @Patric - hier ist es:
Mutex Es wird ziemlich
Semaphore(1,1)
häufig und häufig weltweit verwendet (anwendungsweit, ansonsten wohllock
besser geeignet). Man würde global verwenden,Mutex
wenn ein Knoten aus einer global zugänglichen Liste gelöscht wird (als letztes soll ein anderer Thread etwas tun, während Sie den Knoten löschen). Wenn Sie feststellen,Mutex
ob ein anderer Thread versucht, dasselbeMutex
zu erfassen, wird er in den Ruhezustand versetzt, bis derselbe Thread, der den Erwerb erhalten hat, ihnMutex
freigibt.Ein gutes Beispiel für die Erstellung eines globalen Mutex ist @deepee
dann benutze wie:
Hoffe das spart dir etwas Zeit.
quelle
Wikipedia hat einen großartigen Abschnitt über die Unterschiede zwischen Semaphoren und Mutexen :
quelle
Nach meinem Verständnis kann ein Mutex nur innerhalb eines einzelnen Prozesses verwendet werden, jedoch über mehrere Threads hinweg, während ein Semaphor über mehrere Prozesse hinweg und über die entsprechenden Thread-Sätze hinweg verwendet werden kann.
Außerdem ist ein Mutex binär (entweder gesperrt oder entsperrt), während ein Semaphor den Begriff des Zählens oder eine Warteschlange mit mehr als einer Anforderung zum Sperren und Entsperren hat.
Könnte jemand meine Erklärung überprüfen? Ich spreche im Zusammenhang mit Linux, insbesondere Red Hat Enterprise Linux (RHEL) Version 6, die Kernel 2.6.32 verwendet.
quelle
Verwenden der C-Programmierung unter einer Linux-Variante als Basis für Beispiele.
Sperren:
• Normalerweise ist eine sehr einfache Konstrukt-Binärdatei im Betrieb entweder gesperrt oder entsperrt
• Kein Konzept für Thread-Besitz, Priorität, Sequenzierung usw.
• Normalerweise eine Drehsperre, bei der der Thread kontinuierlich die Verfügbarkeit der Sperren überprüft.
• Verlässt sich normalerweise auf atomare Operationen, z. B. Testen und Setzen, Vergleichen und Tauschen, Abrufen und Hinzufügen usw.
• Erfordert normalerweise Hardware-Unterstützung für den atomaren Betrieb.
Dateisperren:
• Wird normalerweise verwendet, um den Zugriff auf eine Datei über mehrere Prozesse zu koordinieren.
• Mehrere Prozesse können die Lesesperre halten. Wenn jedoch ein einzelner Prozess die Schreibsperre hält, darf kein anderer Prozess eine Lese- oder Schreibsperre erwerben.
• Beispiel: Herde, fcntl etc ..
Mutex:
• Mutex-Funktionsaufrufe funktionieren normalerweise im Kernelraum und führen zu Systemaufrufen.
• Es verwendet das Konzept des Eigentums. Nur der Thread, der derzeit den Mutex enthält, kann ihn entsperren.
• Mutex ist nicht rekursiv (Ausnahme: PTHREAD_MUTEX_RECURSIVE).
• Wird normalerweise in Verbindung mit Bedingungsvariablen verwendet und als Argumente an z. B. pthread_cond_signal, pthread_cond_wait usw. übergeben.
• Einige UNIX-Systeme ermöglichen die Verwendung von Mutex durch mehrere Prozesse, obwohl dies möglicherweise nicht auf allen Systemen erzwungen wird.
Semaphor:
• Dies ist eine vom Kernel gepflegte Ganzzahl, deren Werte nicht unter Null fallen dürfen.
• Es kann verwendet werden, um Prozesse zu synchronisieren.
• Der Wert des Semaphors kann auf einen Wert größer als 1 festgelegt werden. In diesem Fall gibt der Wert normalerweise die Anzahl der verfügbaren Ressourcen an.
• Ein Semaphor, dessen Wert auf 1 und 0 beschränkt ist, wird als binäres Semaphor bezeichnet.
quelle
Supporting ownership
,maximum number of processes share lock
und dasmaximum number of allowed processes/threads in critical section
sind drei Hauptfaktoren, die den Namen / Typ des gleichzeitigen Objekts mit dem allgemeinen Namen von bestimmenlock
. Da der Wert dieser Faktoren binär ist (zwei Zustände hat), können wir sie in einer 3 * 8-Wahrheitstabelle zusammenfassen.Fühlen Sie sich frei, diese Tabelle zu bearbeiten oder zu erweitern. Ich habe sie als ASCII-Tabelle veröffentlicht, damit sie bearbeitet werden kann :)
quelle