Sperren im Zusammenhang mit der Programmierung sind Synchronisationsmechanismen, die zur Steuerung des Zugriffs auf gemeinsame Ressourcen verwendet werden. Sie verhindern Rassenbedingungen, bei denen mehrere Threads oder Prozesse versuchen, dieselben Daten gleichzeitig zu ändern, was zu unvorhersehbaren und falschen Ergebnissen führt. So verwenden Sie Schlösser sowie Variationen und Überlegungen:
Grundkonzepte:
* gegenseitiger Ausschluss: Ein Schloss stellt sicher, dass nur ein Faden das Schloss gleichzeitig halten kann. Jeder andere Faden, der versucht, das Schloss zu erwerben, wird blockiert, bis das Schloss veröffentlicht wird. Dies garantiert den gegenseitigen Ausschluss - nur ein Thread kann auf den kritischen Abschnitt (den von der Sperre geschützten Code) gleichzeitig zugreifen.
* das Schloss erfassen: Vor dem Zugriff auf eine gemeinsame Ressource muss ein Thread das Schloss erwerben (oder erhalten).
* das Schloss veröffentlichen: Nach dem Zugriff auf die freigegebene Ressource muss der Thread die Sperre freigeben (oder entsperren), sodass andere Threads darauf zugreifen können.
* Deadlocks: Ein Deadlock tritt auf, wenn zwei oder mehr Fäden auf unbestimmte Zeit blockiert werden und darauf warten, dass sich die von ihnen benötigten Schlösser freigeben. Sorgfältiges Design und die Bestellung des Schlosseserwerbs sind von entscheidender Bedeutung, um Deadlocks zu vermeiden.
Beispiel (konzeptionelle Python):
`` `Python
Threading importieren
Shared_resource =0
lock =threading.lock ()
Def Increment_Resource ():
Global Shared_resource
lock.acquire () # Erwerben Sie das Schloss
versuchen:
Shared_resource +=1
Endlich:
lock.release () # Freisetzung das Schloss, auch wenn Ausnahmen auftreten
Threads =[]
für i in Reichweite (10):
thread =threading.thread (target =increment_resource)
threads.append (Thread)
thread.start ()
Für Threads in Threads:
thread.join ()
print (f "endgültiger Wert von Shared_resource:{Shared_resource}") # sollte 10 sein
`` `
In diesem Beispiel:
* `threading.lock ()` erstellt ein Sperrobjekt.
* `lock.acquire ()` Versuche, das Schloss zu erwerben. Wenn ein anderer Thread die Sperre enthält, blockiert dieser Anruf, bis das Schloss veröffentlicht wird.
* `lock.release ()` veröffentlicht das Schloss. Der Block "Try ..." schließlich stellt sicher, dass die Sperre immer veröffentlicht wird, auch wenn eine Ausnahme in der Funktion "Increment_Resource" auftritt.
Arten von Sperren (Variationen):
* rekursive Schlösser (Wiedereintrittsschlösser): Lassen Sie denselben Faden das Schloss mehrmals ohne Blockierung erwerben. Nützlich in Situationen, in denen sich eine Funktion rekursiv aufruft und auf eine gemeinsame Ressource zugreifen muss.
* Leseschreiberschlösser: Lassen Sie mehrere Threads die gemeinsame Ressource gleichzeitig lesen, aber nur ein Thread kann gleichzeitig schreiben. Dies verbessert die Parallelität im Vergleich zu einer einfachen Mutex -Sperre.
* Zustandsvariablen: Wird in Verbindung mit Schlösser verwendet, damit Threads darauf warten, dass bestimmte Bedingungen wahr werden, bevor er auf eine gemeinsame Ressource zugreift. Sie bieten eine ausgefeiltere Synchronisation als einfache Schlösser.
* Semaphoren: Verallgemeinern Schlösser; Sie ermöglichen eine bestimmte Anzahl von Threads, gleichzeitig auf eine gemeinsam genutzte Ressource zugreifen zu können. Ein Semaphor mit einer Anzahl von 1 ist im Wesentlichen ein Mutex -Schloss.
Wichtige Überlegungen:
* Granularität sperren: Wählen Sie das angemessene Granularitätsniveau für Ihre Schlösser. Zu feinkörnige Verriegelung kann zu übermäßigem Overhead führen, während zu grobkörnige Verriegelung die Parallelität einschränken kann.
* Deadlock Prevention: Erwerben Sie immer Schlösser in der gleichen Reihenfolge, um Deadlocks zu vermeiden. Verwenden Sie Techniken wie Deadlock -Erkennung und Vermeidung, um das Risiko zu mildern.
* Hunger: Stellen Sie sicher, dass kein Faden ständig vom Erwerb eines Schlosses blockiert wird. Fairness -Mechanismen können dazu beitragen, Hunger zu verhindern.
* Leistung: Schlösser führen Overhead ein. Betrachten Sie gegebenenfalls alternative Synchronisationsmechanismen wie Atomoperationen oder lockfreie Datenstrukturen.
Die spezifische Implementierung von Sperren variiert zwischen den Programmiersprachen. Die hier bereitgestellten Beispiele und Konzepte sind allgemein und wenden sich allgemein an. Die genaue Syntax und die verfügbaren Arten von Sperren unterscheiden sich jedoch in Sprachen wie Java, C ++, C#, GO usw.