Schlösser werden noch benötigt. Ich werde versuchen zu erklären, warum sie gebraucht werden.
Jede Operation / Anweisung wird im Interpreter ausgeführt. GIL stellt sicher, dass der Interpreter zu einem bestimmten Zeitpunkt von einem einzelnen Thread gehalten wird . Und Ihr Programm mit mehreren Threads funktioniert in einem einzigen Interpreter. Zu einem bestimmten Zeitpunkt wird dieser Interpreter von einem einzelnen Thread gehalten. Es bedeutet , dass nur Threads, die Interpreter Halten läuft zu jedem Zeitpunkt der Zeit.
Angenommen, es gibt zwei Threads, z. B. t1 und t2, und beide möchten zwei Anweisungen ausführen, die den Wert einer globalen Variablen lesen und inkrementieren.
global var
read_var = var
var = read_var + 1
Wie oben beschrieben, stellt GIL nur sicher, dass zwei Threads einen Befehl nicht gleichzeitig ausführen können, was bedeutet, dass beide Threads read_var = var
zu einem bestimmten Zeitpunkt nicht ausgeführt werden können. Aber sie können Anweisungen nacheinander ausführen, und Sie können immer noch Probleme haben. Betrachten Sie diese Situation:
- Angenommen, read_var ist 0.
- GIL wird vom Gewinde t1 gehalten.
- t1 wird ausgeführt
read_var = var
. Read_var in t1 ist also 0. GIL stellt nur sicher, dass diese Leseoperation zu diesem Zeitpunkt für keinen anderen Thread ausgeführt wird.
- GIL wird dem Thread t2 gegeben.
- t2 wird ausgeführt
read_var = var
. Aber read_var ist immer noch 0. Also ist read_var in t2 0.
- GIL wird zu t1 gegeben.
- t1 wird ausgeführt
var = read_var+1
und var wird 1.
- GIL wird zu t2 gegeben.
- t2 denkt read_var = 0, weil es das ist, was es liest.
- t2 wird ausgeführt
var = read_var+1
und var wird 1.
- Unsere Erwartung war, dass
var
2 werden sollte.
- Daher muss eine Sperre verwendet werden, um das Lesen und Inkrementieren als atomare Operation aufrechtzuerhalten.
- Will Harris 'Antwort erklärt es anhand eines Codebeispiels.