Gibt es einen Unterschied zwischen einem binären Semaphor und einem Mutex oder sind sie im Wesentlichen gleich?
Gibt es einen Unterschied zwischen einem binären Semaphor und einem Mutex oder sind sie im Wesentlichen gleich?
Antworten:
Sie sind NICHT dasselbe. Sie werden für verschiedene Zwecke verwendet!
Während beide Arten von Semaphoren einen vollständigen / leeren Status haben und dieselbe API verwenden, ist ihre Verwendung sehr unterschiedlich.
Semaphore für gegenseitigen Ausschluss Semaphore für
gegenseitigen Ausschluss werden zum Schutz gemeinsam genutzter Ressourcen (Datenstruktur, Datei usw.) verwendet.
Ein Mutex-Semaphor gehört der Aufgabe, die es übernimmt. Wenn Task B versucht, einen Mutex zu speichern, der derzeit von Task A gehalten wird, gibt der Aufruf von Task B einen Fehler zurück und schlägt fehl.
Mutexe verwenden immer die folgende Reihenfolge:
- SemTake - Kritischer Abschnitt - SemGive
Hier ist ein einfaches Beispiel:
Faden A Faden B. Nimm Mutex Zugangsdaten ... Nimm Mutex <== Wird blockieren ... Geben Sie Mutex-Zugriffsdaten <== Unblocks ... Gib Mutex
Binäres Semaphor
Binäres Semaphor befasst sich mit einer völlig anderen Frage:
Task A Task B
... Take BinSemaphore <== wait for something
Do Something Noteworthy
Give BinSemaphore do something <== unblocks
Beachten Sie, dass es bei einem binären Semaphor für B in Ordnung ist, das Semaphor zu nehmen und A es zu geben.
Wiederum schützt ein binäres Semaphor eine Ressource NICHT vor dem Zugriff. Der Akt des Gebens und Nehmens eines Semaphors ist grundlegend entkoppelt.
Für dieselbe Aufgabe ist es normalerweise wenig sinnvoll, dasselbe binäre Semaphor zu geben und anzunehmen.
Semaphoren eignen sich daher besser für einige Synchronisationsprobleme wie Produzent-Konsument.
Unter Windows ähneln binäre Semaphore eher Ereignisobjekten als Mutexen.
Mutex can be released only by thread that had acquired it
- Ich habe gerade mit einem einfachen pthread_mutex-basierten Programm versucht, ein Thread kann Mutex entsperren, der im Haupt-Thread gesperrt ist
Das Toilettenbeispiel ist eine erfreuliche Analogie:
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
Schöne Artikel zum Thema:
Aus Teil 2:
Der Mutex ähnelt den Prinzipien des binären Semaphors mit einem wesentlichen Unterschied: dem Prinzip des Eigentums. Eigentum ist das einfache Konzept, dass eine Aufgabe, die einen Mutex sperrt (erwirbt), nur von ihm entsperrt (freigegeben) werden kann. Wenn eine Aufgabe versucht, einen Mutex zu entsperren, den sie nicht gesperrt hat (also nicht besitzt), tritt eine Fehlerbedingung auf, und vor allem wird der Mutex nicht entsperrt. Wenn das Objekt des gegenseitigen Ausschlusses kein Eigentum hat, ist es unabhängig von seiner Bezeichnung kein Mutex.
Da keine der obigen Antworten die Verwirrung beseitigt, ist hier eine, die meine Verwirrung beseitigt hat.
Genau genommen ist ein Mutex ein Sperrmechanismus, mit dem der Zugriff auf eine Ressource synchronisiert wird. Nur eine Aufgabe (kann ein Thread oder ein Prozess sein, der auf der Betriebssystemabstraktion basiert) kann den Mutex erfassen. Dies bedeutet, dass mit Mutex Eigentum verbunden ist und nur der Eigentümer die Sperre (Mutex) aufheben kann.
Semaphor ist ein Signalmechanismus ( Signal „Ich bin fertig, du kannst weitermachen“). Wenn Sie beispielsweise auf Ihrem Handy Songs anhören (nehmen Sie es als eine Aufgabe an) und gleichzeitig Ihr Freund Sie anruft, wird ein Interrupt ausgelöst, bei dem eine Interrupt-Serviceroutine (ISR) der Anrufverarbeitungsaufgabe signalisiert, dass sie aufwacht .
Ihre Synchronisationssemantik ist sehr unterschiedlich:
Als solches kann man einen Mutex als ein Token sehen, das von Aufgabe zu Aufgabe weitergegeben wird, und ein Semaphor als Verkehrsrotlicht (es signalisiert jemandem, dass es fortfahren kann).
Auf theoretischer Ebene unterscheiden sie sich semantisch nicht. Sie können einen Mutex mit Semaphoren implementieren oder umgekehrt (siehe hier für ein Beispiel). In der Praxis ist die Implementierung 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 auf einen leichteren Synchronisationsmechanismus abzielt. Im Orakel-Sprachgebrauch werden Mutexe als Latches und Semaphore als Wartezeiten bezeichnet .
Auf der untersten Ebene verwenden sie eine Art Atomtest- und Einstellmechanismus . Dies liest den aktuellen Wert eines Speicherorts, berechnet eine Art Bedingung und schreibt einen Wert an diesem Ort in einem einzelnen Befehl aus, der nicht unterbrochen werden kann . Dies bedeutet, dass Sie einen Mutex erwerben und testen können, ob jemand anderes ihn vor Ihnen hatte.
Bei einer typischen Mutex-Implementierung führt ein Prozess oder Thread die Test-and-Set-Anweisung aus und bewertet, ob der Mutex durch irgendetwas anderes festgelegt wurde. Ein wichtiger Punkt hierbei ist, dass es keine Interaktion mit dem Scheduler gibt , sodass wir keine Ahnung haben (und es uns egal ist), wer die Sperre gesetzt hat. Dann geben wir entweder unsere Zeitscheibe auf und versuchen es erneut, wenn die Aufgabe neu geplant wird, oder führen eine Drehsperre aus . Ein Spin Lock 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 mit der Ausführung unseres geschützten Codes (als kritischer Abschnitt bezeichnet ) fertig sind, setzen wir den Mutex-Wert einfach auf Null oder was auch immer "klar" bedeutet. Wenn mehrere Aufgaben versuchen, den Mutex abzurufen, erhält die nächste Aufgabe, die nach der Freigabe des Mutex geplant wird, Zugriff auf die Ressource. Normalerweise verwenden Sie Mutexe, um eine synchronisierte Ressource zu steuern, bei der exklusiver Zugriff nur für sehr kurze Zeiträume erforderlich ist, normalerweise, um eine Aktualisierung einer gemeinsam genutzten Datenstruktur vorzunehmen.
Ein Semaphor ist eine synchronisierte Datenstruktur (normalerweise unter Verwendung eines Mutex) mit einer Anzahl und einigen Systemaufruf-Wrappern, die mit dem Scheduler etwas tiefer interagieren als die Mutex-Bibliotheken. Semaphoren werden inkrementiert und dekrementiert und zum Blockieren von Aufgaben verwendet, bis etwas anderes fertig ist. Ein einfaches Beispiel hierfür finden Sie unter Producer / Consumer Problem . Semaphore werden auf einen bestimmten Wert initialisiert - ein binäres Semaphor ist nur ein Sonderfall, in dem das Semaphor auf 1 initialisiert wird. Das Posten auf einem Semaphor hat den Effekt, dass ein Wartevorgang aktiviert 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 Fall eines binären Semaphors besteht der hauptsächliche praktische Unterschied zwischen den beiden in der Art der Systemdienste, die die tatsächliche Datenstruktur umgeben.
EDIT: Wie evan zu Recht betont hat, verlangsamen Spinlocks eine einzelne Prozessormaschine. Sie würden einen Spinlock nur auf einer Multiprozessor-Box verwenden, da auf einem einzelnen Prozessor der Prozess, der den Mutex enthält, ihn niemals zurücksetzt, während eine andere Aufgabe ausgeführt wird. Spinlocks sind nur auf Multiprozessor-Architekturen nützlich.
futex
-Systemaufruf vorhanden, um Mutex- / Semaphor-Implementierungen im Benutzerbereich mit geringer Latenz zu unterstützen. en.wikipedia.org/wiki/Futex ) Auf dem schnellen Pfad ohne Konflikte oder wenn die Ressource bald verfügbar wird, haben Sie nie den Overhead von ein Systemaufruf. Aber Sie verbringen nicht mehr als ein paar Mikrosekunden damit, zu warten (sich zu drehen). Das Optimieren der Parameter für Spin-Loop-Backoff und Warten hängt natürlich von der Hardware und der Arbeitslast ab, aber die Standardbibliothek bietet normalerweise eine vernünftige Auswahl.
Obwohl Mutex und Semaphoren als Synchronisationsprimitive verwendet werden, gibt es einen großen Unterschied zwischen ihnen. Im Fall von Mutex kann nur der Thread, der den Mutex gesperrt oder erworben hat, ihn entsperren. Im Fall eines Semaphors kann ein auf ein Semaphor wartender Thread von einem anderen Thread signalisiert werden. Einige Betriebssysteme unterstützen die Verwendung von Mutex und Semaphoren zwischen Prozessen. In der Regel wird die Verwendung im gemeinsam genutzten Speicher erstellt.
Mutex: Angenommen, wir haben einen kritischen Abschnittsthread, auf den T1 zugreifen möchte, dann folgen die folgenden Schritte. T1:
Binäres Semaphor: Es funktioniert basierend auf dem Signalisieren von Warten und Signalisieren. Wartezeit (en) verringern den "s" -Wert um eins Normalerweise wird der "s" -Wert mit dem Wert "1" initialisiert, die Signale erhöhen den "s" -Wert um eins. Wenn der Wert "s" 1 ist, bedeutet dies, dass niemand einen kritischen Abschnitt verwendet. Wenn der Wert 0 ist, bedeutet dies, dass ein kritischer Abschnitt verwendet wird. Angenommen, Thread T2 verwendet einen kritischen Abschnitt, dann folgen die folgenden Schritte. T2:
Der Hauptunterschied zwischen Mutex und Binärsemaphor besteht in Mutext, wenn der Thread den kritischen Abschnitt sperrt, dann muss er den kritischen Abschnitt entsperren, kein anderer Thread kann ihn entsperren. Im Fall des Binärsemaphors, wenn ein Thread den kritischen Abschnitt mit der Funktion wait (s) sperrt, ist der Wert von s wird zu "0" und niemand kann darauf zugreifen, bis der Wert von "s" zu 1 wird. Angenommen, ein anderes Thread ruft Signal (e) auf, dann wird der Wert von "s" zu 1 und es ermöglicht anderen Funktionen, einen kritischen Abschnitt zu verwenden. Daher hat der Thread im binären Semaphor keinen Besitz.
Unter Windows gibt es zwei Unterschiede zwischen Mutexen und binären Semaphoren:
Ein Mutex kann nur von dem Thread freigegeben werden, der Eigentümer ist, dh dem Thread, der zuvor die Wait-Funktion aufgerufen hat (oder der beim Erstellen den Besitz übernommen hat). Ein Semaphor kann von jedem Thread freigegeben werden.
Ein Thread kann eine Wartefunktion für einen Mutex wiederholt aufrufen, ohne ihn zu blockieren. Wenn Sie jedoch eine Wartefunktion für ein binäres Semaphor zweimal aufrufen, ohne das dazwischen liegende Semaphor freizugeben, wird der Thread blockiert.
Sie verwenden offensichtlich Mutex, um Daten in einem Thread zu sperren, auf die gleichzeitig ein anderer Thread zugreift. Angenommen, Sie haben gerade angerufen lock()
und sind gerade dabei, auf Daten zuzugreifen. Dies bedeutet, dass Sie nicht erwarten, dass ein anderer Thread (oder eine andere Instanz desselben Thread-Codes) auf dieselben Daten zugreift, die durch denselben Mutex gesperrt sind. Das heißt, wenn es der gleiche Thread-Code ist, der auf einer anderen Thread-Instanz ausgeführt wird, trifft die Sperre, dann dielock()
sollte dort den Kontrollfluss blockieren. Dies gilt für einen Thread, der einen anderen Thread-Code verwendet, der ebenfalls auf dieselben Daten zugreift und der auch von demselben Mutex gesperrt wird. In diesem Fall sind Sie noch dabei, auf die Daten zuzugreifen, und Sie können beispielsweise weitere 15 Sekunden benötigen, um die Mutex-Entsperrung zu erreichen (sodass der andere Thread, der in der Mutex-Sperre blockiert wird, entsperrt wird und die Steuerung dies zulässt Zugriff auf die Daten). Erlauben Sie um jeden Preis einem weiteren Thread, denselben Mutex zu entsperren, und lassen Sie wiederum den Thread, der bereits in der Mutex-Sperre wartet (blockiert), die Blockierung aufzuheben und auf die Daten zuzugreifen? Hoffe du hast was ich hier sage? Gemäß vereinbarter universeller Definition!
Wenn Sie also besonders darauf bedacht sind, Binärsemaphor anstelle von Mutex zu verwenden, sollten Sie beim Sperren und Entsperren der Sperren sehr vorsichtig sein. Ich meine, dass jeder Kontrollfluss, der jede Sperre trifft, einen Entsperranruf treffen sollte, außerdem sollte es keine "erste Entsperrung" geben, sondern immer "erste Sperre".
Mutex werden für "Verriegelungsmechanismen" verwendet. Jeweils ein Prozess kann eine gemeinsam genutzte Ressource verwenden
wohingegen
Semaphore werden für "Signalmechanismen" wie "Ich bin fertig, jetzt kann ich weitermachen" verwendet.
Mythos:
Ein paar Artikel besagen, dass "binäres Semaphor und Mutex gleich sind" oder "Semaphor mit dem Wert 1 ist Mutex", aber der grundlegende Unterschied ist, dass Mutex nur von einem Thread freigegeben werden kann, der es erworben hat, während Sie Semaphor von jedem anderen Thread signalisieren können
Wichtige Punkte:
• Ein Thread kann mehr als eine Sperre (Mutex) erhalten.
• Ein Mutex kann nur dann mehrmals gesperrt werden, wenn es sich um einen rekursiven Mutex handelt. Hier sollte das Sperren und Entsperren für Mutex identisch sein
• Wenn ein Thread, der bereits einen Mutex gesperrt hat, versucht, den Mutex erneut zu sperren, wird er in die Warteliste dieses Mutex aufgenommen, was zu einem Deadlock führt.
• Binäres Semaphor und Mutex sind ähnlich, aber nicht gleich.
• Mutex ist aufgrund der damit verbundenen Schutzprotokolle ein kostspieliger Betrieb.
• Das Hauptziel von Mutex ist das Erreichen eines atomaren Zugriffs oder das Sperren von Ressourcen
Ein Mutex steuert den Zugriff auf eine einzelne gemeinsam genutzte Ressource. Es bietet Vorgänge, um Zugriff auf diese Ressource zu erhalten () und sie anschließend freizugeben () .
Ein Semaphor steuert den Zugriff auf einen gemeinsam genutzten Ressourcenpool. Es bietet Operationen für Wait (), bis eine der Ressourcen im Pool verfügbar ist, und Signal (), wenn sie an den Pool zurückgegeben wird.
Wenn die Anzahl der Ressourcen, die ein Semaphor schützt, größer als 1 ist, wird es als Zählsemaphor bezeichnet . Wenn es eine Ressource steuert, wird es als Boolesches Semaphor bezeichnet . Ein boolesches Semaphor entspricht einem Mutex.
Somit ist ein Semaphor eine Abstraktion auf höherer Ebene als Mutex. Ein Mutex kann mit einem Semaphor implementiert werden, aber nicht umgekehrt.
Die modifizierte Frage lautet: Was ist der Unterschied zwischen einem Mutex und einem "binären" Semaphor in "Linux"?
Antwort: Im Folgenden sind die Unterschiede aufgeführt: i) Gültigkeitsbereich - Der Gültigkeitsbereich von Mutex befindet sich in einem Prozessadressraum, der ihn erstellt hat und für die Synchronisierung von Threads verwendet wird. Während Semaphor über den gesamten Prozessraum hinweg verwendet werden kann, kann es für die Interprozesssynchronisation verwendet werden.
ii) Mutex ist leicht und schneller als Semaphor. Futex ist noch schneller.
iii) Mutex kann von demselben Thread mehrmals erfolgreich erworben werden, unter der Bedingung, dass er gleich oft freigegeben wird. Ein anderer Thread, der versucht zu erfassen, wird blockiert. Wenn im Falle eines Semaphors derselbe Prozess versucht, es erneut zu erfassen, blockiert es, da es nur einmal erfasst werden kann.
Unterschied zwischen binärem Semaphor und Mutex: EIGENTUM: Semaphore können auch von einem nicht aktuellen Eigentümer signalisiert (gepostet) werden. Es bedeutet, dass Sie einfach von jedem anderen Thread aus posten können, obwohl Sie nicht der Eigentümer sind.
Semaphor ist eine öffentliche Eigenschaft in Bearbeitung. Es kann einfach von einem Nicht-Eigentümer-Thread gepostet werden. Bitte markieren Sie diesen Unterschied in Fettdruck, es bedeutet viel.
Mutex arbeitet daran, kritische Bereiche zu blockieren, aber Semaphore arbeitet an der Zählung.
http://www.geeksforgeeks.org/archives/9102 wird ausführlich besprochen.
Mutex
ist ein Sperrmechanismus, mit dem der Zugriff auf eine Ressource synchronisiert wird.
Semaphore
ist Signalmechanismus.
Es liegt am Programmierer, ob er / sie anstelle von Mutex ein binäres Semaphor verwenden möchte.
Abgesehen von der Tatsache, dass Mutexe einen Eigentümer haben, können die beiden Objekte für unterschiedliche Verwendungszwecke optimiert werden. Mutexe sind nur für kurze Zeit gedacht. Ein Verstoß gegen diese Bestimmungen kann zu schlechter Leistung und unfairer Planung führen. Beispielsweise kann einem laufenden Thread gestattet werden, einen Mutex abzurufen, obwohl bereits ein anderer Thread darauf blockiert ist. Semaphore können mehr Fairness bieten oder Fairness kann unter Verwendung mehrerer Bedingungsvariablen erzwungen werden.
sem_post()
für SCHED_FIFO
und SCHED_RR
(diese beide sind nicht standardmäßig): der höchste Priorität Thread, und wenn es mehr mit der gleichen Priorität, der Thread, der die längsten gewartet hat. OpenSolaris folgt dieser FIFO-Regel bis zu einem gewissen Grad, auch bei normaler Planung. Für glibc und FreeBSD sind das Entsperren eines einfachen Mutex (dh kein Prioritätsschutz oder das Erben von Prioritäten) und das Posten eines Semaphors im Grunde dasselbe. Markieren Sie das Objekt als entsperrt und rufen Sie den Kernel auf, um einen zu aktivieren, falls möglicherweise Threads warten.
In Windows ist der Unterschied wie folgt. MUTEX: Prozess, der das Warten erfolgreich ausführt , muss ein Signal ausführen und umgekehrt. BINARY Semaphore: Verschiedene Prozesse ausführen kann warten oder Signal auf einem Semaphor - Operation.
Während ein binäres Semaphor als Mutex verwendet werden kann, ist ein Mutex ein spezifischerer Anwendungsfall, da nur der Prozess, der den Mutex gesperrt hat, ihn entsperren soll. Diese Eigentumsbeschränkung ermöglicht den Schutz vor:
Diese Einschränkungen sind nicht immer vorhanden, da sie die Geschwindigkeit verschlechtern. Während der Entwicklung Ihres Codes können Sie diese Überprüfungen vorübergehend aktivieren.
Sie können beispielsweise das Attribut Fehlerprüfung in Ihrem Mutex aktivieren. Fehler beim Überprüfen der Mutexe, EDEADLK
wenn Sie versuchen, denselben zweimal zu sperren, und EPERM
wenn Sie einen Mutex entsperren, der nicht Ihnen gehört.
pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);
Nach der Initialisierung können wir diese Überprüfungen wie folgt in unseren Code einfügen:
if(pthread_mutex_unlock(&mutex)==EPERM)
printf("Unlock failed:Mutex not owned by this thread\n");
Das Konzept war mir klar, nachdem ich die obigen Beiträge durchgesehen hatte. Aber es gab noch einige Fragen. Also habe ich diesen kleinen Code geschrieben.
Wenn wir versuchen, ein Semaphor zu geben, ohne es zu nehmen, geht es durch. Wenn Sie jedoch versuchen, einen Mutex zu geben, ohne ihn zu nehmen, schlägt dies fehl. Ich habe dies auf einer Windows-Plattform getestet. Aktivieren Sie USE_MUTEX, um denselben Code mit einem MUTEX auszuführen.
#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1
DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );
HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;
int main(void)
{
#ifdef USE_MUTEX
ghMutex = CreateMutex( NULL, FALSE, NULL);
if (ghMutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
#else
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
#endif
// Create thread 1.
Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);
if ( Handle_Of_Thread_1 == NULL)
{
printf("Create first thread problem \n");
return 1;
}
/* sleep for 5 seconds **/
Sleep(5 * 1000);
/*Create thread 2 */
Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);
if ( Handle_Of_Thread_2 == NULL)
{
printf("Create second thread problem \n");
return 1;
}
// Sleep for 20 seconds
Sleep(20 * 1000);
printf("Out of the program \n");
return 0;
}
int my_critical_section_code(HANDLE thread_handle)
{
#ifdef USE_MUTEX
if(thread_handle == Handle_Of_Thread_1)
{
/* get the lock */
WaitForSingleObject(ghMutex, INFINITE);
printf("Thread 1 holding the mutex \n");
}
#else
/* get the semaphore */
if(thread_handle == Handle_Of_Thread_1)
{
WaitForSingleObject(ghSemaphore, INFINITE);
printf("Thread 1 holding semaphore \n");
}
#endif
if(thread_handle == Handle_Of_Thread_1)
{
/* sleep for 10 seconds */
Sleep(10 * 1000);
#ifdef USE_MUTEX
printf("Thread 1 about to release mutex \n");
#else
printf("Thread 1 about to release semaphore \n");
#endif
}
else
{
/* sleep for 3 secconds */
Sleep(3 * 1000);
}
#ifdef USE_MUTEX
/* release the lock*/
if(!ReleaseMutex(ghMutex))
{
printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
}
#else
if (!ReleaseSemaphore(ghSemaphore,1,NULL) )
{
printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
}
#endif
return 0;
}
DWORD WINAPI Thread_no_1( LPVOID lpParam )
{
my_critical_section_code(Handle_Of_Thread_1);
return 0;
}
DWORD WINAPI Thread_no_2( LPVOID lpParam )
{
my_critical_section_code(Handle_Of_Thread_2);
return 0;
}
Die Tatsache, dass Sie mit dem Semaphor signalisieren können, dass es eine Ressource verwendet, obwohl es die Ressource nie besaß, lässt mich glauben, dass es bei Semaphoren eine sehr lockere Kopplung zwischen Besitz und Signalisierung gibt.
Mutex wird zum Schutz des vertraulichen Codes und der Daten verwendet, Semaphor wird zum Synchronisieren verwendet. Sie können den vertraulichen Code auch praktisch schützen, es besteht jedoch das Risiko, dass der Schutz durch den anderen Thread durch die Operation V.So The main aufgehoben wird Unterschied zwischen Bi-Semaphor und Mutex ist das Eigentum. Zum Beispiel durch Toilette ist Mutex so, dass man die Toilette betreten und die Tür abschließen kann, niemand anderes kann eintreten, bis der Mann aussteigt, Bi-Semaphor ist so, dass man eintreten kann die Toilette und die Tür abschließen, aber jemand anderes könnte eintreten, indem er den Administrator bittet, die Tür zu öffnen, es ist lächerlich.
Mutex
Mutexe werden normalerweise verwendet, um den Zugriff auf einen Abschnitt des neu eingegebenen Codes zu serialisieren, der nicht von mehr als einem Thread gleichzeitig ausgeführt werden kann. Ein Mutex-Objekt erlaubt nur einen Thread in einen kontrollierten Abschnitt, wodurch andere Threads, die versuchen, Zugriff auf diesen Abschnitt zu erhalten, warten müssen, bis der erste Thread diesen Abschnitt verlassen hat. Die ordnungsgemäße Verwendung eines Mutex zum Schutz einer gemeinsam genutzten Ressource kann gefährlich sein unbeabsichtigte Nebenwirkung. Zwei beliebige RTOS-Aufgaben, die mit unterschiedlichen Prioritäten ausgeführt und über einen Mutex koordiniert werden, bieten die Möglichkeit zur Prioritätsumkehr . Mutex arbeitet im Benutzerbereich .
Semaphor
Semaphor ist ein Signalmechanismus. Semaphor beschränkt die Anzahl gleichzeitiger 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). Es ermöglicht der Anzahl der Threads, auf gemeinsam genutzte Ressourcen zuzugreifen. Die korrekte Verwendung eines Semaphors dient zum Signalisieren von einer Aufgabe zu einer anderen. Metaphern können auch zum Signalisieren von einer Interrupt-Serviceroutine (ISR) zu einer Aufgabe verwendet werden. Das Signalisieren eines Semaphors ist ein nicht blockierendes RTOS-Verhalten und somit ISR-sicher. Da diese Technik die fehleranfällige Notwendigkeit beseitigt, Interrupts auf Aufgabenebene zu deaktivieren. Dies funktioniert im Kernelraum .
Die Antwort kann vom Zielbetriebssystem abhängen. Beispielsweise ermöglicht mindestens eine mir vertraute RTOS-Implementierung mehrere aufeinanderfolgende "get" -Operationen für einen einzelnen Betriebssystem-Mutex, sofern sie alle aus demselben Thread-Kontext stammen. Die Mehrfach-Gets müssen durch eine gleiche Anzahl von Puts ersetzt werden, bevor ein anderer Thread den Mutex erhalten kann. Dies unterscheidet sich von binären Semaphoren, für die unabhängig von den Thread-Kontexten jeweils nur ein Get zulässig ist.
Die Idee hinter dieser Art von Mutex ist, dass Sie ein Objekt schützen, indem Sie nur einem einzelnen Kontext erlauben, die Daten gleichzeitig zu ändern. Selbst wenn der Thread den Mutex erhält und dann eine Funktion aufruft, die das Objekt weiter modifiziert (und den Protector-Mutex um seine eigenen Operationen herum abruft), sollten die Operationen dennoch sicher sein, da sie alle unter einem einzigen Thread ausgeführt werden.
{
mutexGet(); // Other threads can no longer get the mutex.
// Make changes to the protected object.
// ...
objectModify(); // Also gets/puts the mutex. Only allowed from this thread context.
// Make more changes to the protected object.
// ...
mutexPut(); // Finally allows other threads to get the mutex.
}
Wenn Sie diese Funktion verwenden, müssen Sie natürlich sicher sein, dass alle Zugriffe innerhalb eines einzelnen Threads wirklich sicher sind!
Ich bin mir nicht sicher, wie häufig dieser Ansatz ist oder ob er außerhalb der mir bekannten Systeme gilt. Ein Beispiel für diese Art von Mutex finden Sie im ThreadX RTOS.
Mutexe sind im Gegensatz zu Semaphoren Eigentum. Obwohl jedem Thread im Rahmen eines Mutex, kann ein nicht gesperrtes Mutex und sperren den Zugriff auf den gleichen kritischen Abschnitt des Codes erhalten, nur der Thread, der einen Mutex gesperrt sollte es entsperren .
Wie viele Leute hier erwähnt haben, wird ein Mutex verwendet, um einen kritischen Code (kritischer Abschnitt der AKA) zu schützen. Sie erwerben den Mutex (Sperre), geben den kritischen Abschnitt ein und geben den Mutex (Entsperren) im selben Thread frei .
Während Sie ein Semaphor verwenden, können Sie einen Thread auf ein Semaphor warten lassen (z. B. Thread A), bis ein anderer Thread (z. B. Thread B) eine beliebige Aufgabe abgeschlossen hat, und dann das Semaphor für Thread A festlegen, um das Warten zu stoppen und seine Aufgabe fortzusetzen.
Beste Lösung
Der einzige Unterschied ist
1.Mutex -> Sperren und Entsperren gehören einem Thread, der den Mutex sperrt.
2.Semaphore -> Kein Eigentum dh; Wenn ein Thread semwait (s) aufruft, kann jeder andere Thread sempost (s) aufrufen, um die Sperre aufzuheben.
MUTEX
Bis vor kurzem war das Semaphor das einzige schlafende Schloss im Kernel. Die meisten Benutzer von Semaphoren instanziierten ein Semaphor mit einer Zählung von eins und behandelten sie als gegenseitige Ausschlusssperre - eine schlafende Version der Spin-Sperre. Leider sind Semaphoren eher allgemein gehalten und unterliegen keinen Nutzungsbeschränkungen. Dies macht sie nützlich für die Verwaltung des exklusiven Zugriffs in dunklen Situationen, wie z. B. komplizierten Tänzen zwischen dem Kernel und dem Benutzerbereich. Dies bedeutet jedoch auch, dass ein einfacheres Sperren schwieriger ist und das Fehlen erzwungener Regeln jede Art von automatisiertem Debugging oder Durchsetzung von Einschränkungen unmöglich macht. Auf der Suche nach einem einfacheren Schlafschloss haben die Kernel-Entwickler den Mutex eingeführt. Ja, wie Sie es jetzt gewohnt sind, das ist ein verwirrender Name. Lassen Sie uns das klarstellen. Der Begriff „Mutex“ ist ein generischer Name für jede Schlafsperre, die den gegenseitigen Ausschluss erzwingt. wie ein Semaphor mit einer Verwendungszahl von eins. In neueren Linux-Kerneln ist das Eigenname „Mutex“ jetzt auch eine bestimmte Art von Schlafsperre, die den gegenseitigen Ausschluss implementiert. Das heißt, ein Mutex ist ein Mutex.
Die Einfachheit und Effizienz des Mutex ergibt sich aus den zusätzlichen Einschränkungen, die er seinen Benutzern auferlegt, und zwar über die Anforderungen des Semaphors hinaus. Im Gegensatz zu einem Semaphor, das das grundlegendste Verhalten gemäß dem ursprünglichen Design von Dijkstra implementiert, hat der Mutex einen strengeren, engeren Anwendungsfall: n Es kann jeweils nur eine Aufgabe den Mutex enthalten. Das heißt, die Verwendungsanzahl eines Mutex ist immer eins.
[1] Linux-Kernel-Entwicklung, dritte Ausgabe Robert Love
Ich denke, die meisten Antworten hier waren verwirrend, insbesondere diejenigen, die besagten, dass Mutex nur durch den Prozess freigesetzt werden kann, der ihn enthält, aber Semaphor kann durch jeden Prozess signalisiert werden. Die obige Zeile ist in Bezug auf das Semaphor etwas vage. Um zu verstehen, sollten wir wissen, dass es zwei Arten von Semaphoren gibt, von denen eine als Zählsemaphor und die andere als binäres Semaphor bezeichnet wird. Beim Zählen behandelt Semaphor den Zugriff auf n Ressourcen, wobei n vor der Verwendung definiert werden kann. Jedes Semaphor hat eine Zählvariable, die die Anzahl der verwendeten Ressourcen beibehält. Zunächst wird sie auf n gesetzt. Jeder Prozess, der eine Ressource verwenden möchte, führt eine wait () - Operation für das Semaphor aus (wodurch die Anzahl verringert wird). Wenn ein Prozess eine Ressource freigibt, führt er eine release () - Operation aus (Erhöhen der Anzahl). Wenn die Zählung 0 wird, Alle Ressourcen werden verwendet. Danach wartet der Prozess, bis die Anzahl größer als 0 wird. Hier ist der Haken: Nur der Prozess, der die Ressource enthält, kann die Anzahl erhöhen. Kein anderer Prozess kann die Anzahl erhöhen. Nur die Prozesse, die eine Ressource enthalten, können die Anzahl und den Prozess erhöhen Wenn Sie erneut auf das Semaphor warten, wird überprüft, und wenn die verfügbare Ressource angezeigt wird, wird die Anzahl erneut verringert. In Bezug auf das binäre Semaphor kann nur der Prozess, der das Semaphor enthält, die Anzahl erhöhen, und die Anzahl bleibt Null, bis das Semaphor nicht mehr verwendet wird und die Anzahl erhöht wird und andere Prozesse die Möglichkeit erhalten, auf das Semaphor zuzugreifen. Hier ist der Haken: Nur der Prozess, der die Ressource enthält, kann die Anzahl erhöhen. Kein anderer Prozess kann die Anzahl erhöhen. Nur die Prozesse, die eine Ressource enthalten, können die Anzahl erhöhen. Der Prozess, der auf das Semaphor wartet, überprüft erneut, ob die Ressource verfügbar ist verringert die Anzahl erneut. In Bezug auf das binäre Semaphor kann nur der Prozess, der das Semaphor enthält, die Anzahl erhöhen, und die Anzahl bleibt Null, bis das Semaphor nicht mehr verwendet wird und die Anzahl erhöht wird und andere Prozesse die Möglichkeit erhalten, auf das Semaphor zuzugreifen. Hier ist der Haken: Nur der Prozess, der die Ressource enthält, kann die Anzahl erhöhen. Kein anderer Prozess kann die Anzahl erhöhen. Nur die Prozesse, die eine Ressource enthalten, können die Anzahl erhöhen. Der Prozess, der auf das Semaphor wartet, überprüft erneut, ob die Ressource verfügbar ist verringert die Anzahl erneut. In Bezug auf das binäre Semaphor kann nur der Prozess, der das Semaphor enthält, die Anzahl erhöhen, und die Anzahl bleibt Null, bis das Semaphor nicht mehr verwendet wird und die Anzahl erhöht wird und andere Prozesse die Möglichkeit erhalten, auf das Semaphor zuzugreifen.
Der Hauptunterschied zwischen binärem Semaphor und Mutex besteht darin, dass Semaphor ein Signalmechanismus und Mutex ein Sperrmechanismus ist, aber binäres Semaphor scheint wie Mutex zu funktionieren, der Verwirrung stiftet, aber beide sind unterschiedliche Konzepte, die für unterschiedliche Arten von Arbeit geeignet sind.