Mit der Programmiersprache Python können Sie Multiprocessing oder Multithreading verwenden. In diesem Lernprogramm erfahren Sie, wie Sie Multithread-Anwendungen in Python schreiben.
Was ist ein Thread?
Ein Thread ist eine Exektionseinheit bei gleichzeitiger Programmierung. Multithreading ist eine Technik, mit der eine CPU viele Aufgaben eines Prozesses gleichzeitig ausführen kann. Diese Threads können einzeln ausgeführt werden, während ihre Prozessressourcen gemeinsam genutzt werden.
Was ist ein Prozess?
Ein Prozess ist im Grunde das Programm, das ausgeführt wird. Wenn Sie eine Anwendung auf Ihrem Computer starten (z. B. einen Browser oder einen Texteditor), erstellt das Betriebssystem einen Prozess.
Was ist Multithreading in Python?
Multithreading in der Python- Programmierung ist eine bekannte Technik, bei der mehrere Threads in einem Prozess ihren Datenraum mit dem Hauptthread teilen, wodurch der Informationsaustausch und die Kommunikation innerhalb von Threads einfach und effizient werden. Fäden sind leichter als Prozesse. Multi-Threads können einzeln ausgeführt werden, während ihre Prozessressourcen gemeinsam genutzt werden. Der Zweck von Multithreading besteht darin, mehrere Aufgaben und Funktionszellen gleichzeitig auszuführen.
Was ist Multiprocessing?
Mit Multiprocessing können Sie mehrere unabhängige Prozesse gleichzeitig ausführen. Diese Prozesse teilen ihre Ressourcen nicht und kommunizieren nicht über IPC.
Python Multithreading vs Multiprocessing
Stellen Sie sich das folgende Szenario vor, um Prozesse und Threads zu verstehen: Eine EXE-Datei auf Ihrem Computer ist ein Programm. Wenn Sie es öffnen, lädt das Betriebssystem es in den Speicher und die CPU führt es aus. Die Instanz des Programms, das jetzt ausgeführt wird, wird als Prozess bezeichnet.
Jeder Prozess besteht aus zwei grundlegenden Komponenten:
- Der Code
- Die Daten
Jetzt kann ein Prozess einen oder mehrere Unterteile enthalten, die als Threads bezeichnet werden. Dies hängt von der Betriebssystemarchitektur ab. Sie können sich einen Thread als einen Teil des Prozesses vorstellen, der vom Betriebssystem separat ausgeführt werden kann.
Mit anderen Worten, es handelt sich um einen Befehlsstrom, der vom Betriebssystem unabhängig ausgeführt werden kann. Threads innerhalb eines einzelnen Prozesses teilen die Daten dieses Prozesses und sind so konzipiert, dass sie zusammenarbeiten, um die Parallelität zu erleichtern.
In diesem Tutorial lernen Sie:
- Was ist ein Thread?
- Was ist ein Prozess?
- Was ist Multithreading?
- Was ist Multiprocessing?
- Python Multithreading vs Multiprocessing
- Warum Multithreading verwenden?
- Python MultiThreading
- Die Thread- und Threading-Module
- Das Thread-Modul
- Das Threading-Modul
- Deadlocks und Rennbedingungen
- Threads synchronisieren
- Was ist GIL?
- Warum wurde GIL gebraucht?
Warum Multithreading verwenden?
Mit Multithreading können Sie eine Anwendung in mehrere Unteraufgaben aufteilen und diese Aufgaben gleichzeitig ausführen. Wenn Sie Multithreading ordnungsgemäß verwenden, können Anwendungsgeschwindigkeit, Leistung und Rendering verbessert werden.
Python MultiThreading
Python unterstützt Konstrukte sowohl für Multiprocessing als auch für Multithreading. In diesem Tutorial konzentrieren Sie sich hauptsächlich auf die Implementierung von Multithread- Anwendungen mit Python. Es gibt zwei Hauptmodule, mit denen Threads in Python verarbeitet werden können:
- Das Thread- Modul und
- Das Einfädeln Modul
In Python gibt es jedoch auch eine sogenannte globale Interpreter-Sperre (GIL). Es ermöglicht nicht viel Leistungsgewinn und kann sogar die Leistung einiger Multithread-Anwendungen verringern . In den nächsten Abschnitten dieses Tutorials erfahren Sie alles darüber.
Die Thread- und Threading-Module
Die beiden Module, die Sie in diesem Tutorial kennenlernen werden, sind das Thread-Modul und das Threading-Modul .
Das Thread-Modul ist jedoch seit langem veraltet. Ab Python 3 wurde es als veraltet eingestuft und ist aus Gründen der Abwärtskompatibilität nur als __thread verfügbar .
Sie sollten das übergeordnete Threading- Modul für Anwendungen verwenden, die Sie bereitstellen möchten. Das Thread-Modul wurde hier nur zu Bildungszwecken behandelt.
Das Thread-Modul
Die Syntax zum Erstellen eines neuen Threads mit diesem Modul lautet wie folgt:
thread.start_new_thread(function_name, arguments)
Okay, jetzt haben Sie die grundlegende Theorie behandelt, um mit dem Codieren zu beginnen. Öffnen Sie also Ihren IDLE oder einen Notizblock und geben Sie Folgendes ein:
import timeimport _threaddef thread_test(name, wait):i = 0while i <= 3:time.sleep(wait)print("Running %s\n" %name)i = i + 1print("%s has finished execution" %name)if __name__ == "__main__":_thread.start_new_thread(thread_test, ("First Thread", 1))_thread.start_new_thread(thread_test, ("Second Thread", 2))_thread.start_new_thread(thread_test, ("Third Thread", 3))
Speichern Sie die Datei und drücken Sie F5, um das Programm auszuführen. Wenn alles richtig gemacht wurde, ist dies die Ausgabe, die Sie sehen sollten:
In den nächsten Abschnitten erfahren Sie mehr über die Rennbedingungen und deren Handhabung
CODE ERKLÄRUNG
- Diese Anweisungen importieren das Zeit- und Thread-Modul, mit dem die Ausführung und Verzögerung der Python-Threads behandelt wird.
- Hier haben Sie eine Funktion namens thread_test definiert, die von der Methode start_new_thread aufgerufen wird. Die Funktion führt eine while-Schleife für vier Iterationen aus und gibt den Namen des Threads aus, der sie aufgerufen hat. Sobald die Iteration abgeschlossen ist, wird eine Meldung ausgegeben, dass der Thread die Ausführung beendet hat.
- Dies ist der Hauptteil Ihres Programms. Hier rufen Sie einfach die Methode start_new_thread mit der Funktion thread_test als Argument auf.
Dadurch wird ein neuer Thread für die Funktion erstellt, die Sie als Argument übergeben, und die Ausführung wird gestartet. Beachten Sie, dass Sie dies (thread _ test) durch jede andere Funktion ersetzen können, die Sie als Thread ausführen möchten.
Das Threading-Modul
Dieses Modul ist die allgemeine Implementierung von Threading in Python und der De-facto-Standard für die Verwaltung von Multithread-Anwendungen. Es bietet im Vergleich zum Thread-Modul eine Vielzahl von Funktionen.

Hier ist eine Liste einiger nützlicher Funktionen, die in diesem Modul definiert sind:
Funktionsname | Beschreibung |
activeCount () | Gibt die Anzahl der noch aktiven Thread- Objekte zurück |
currentThread () | Gibt das aktuelle Objekt der Thread-Klasse zurück. |
aufzählen() | Listet alle aktiven Thread-Objekte auf. |
isDaemon () | Gibt true zurück, wenn der Thread ein Daemon ist. |
ist am Leben() | Gibt true zurück, wenn der Thread noch aktiv ist. |
Thread-Klassenmethoden | |
Start() | Startet die Aktivität eines Threads. Es muss nur einmal für jeden Thread aufgerufen werden, da es bei mehrmaligem Aufruf einen Laufzeitfehler auslöst. |
Lauf() | Diese Methode bezeichnet die Aktivität eines Threads und kann von einer Klasse überschrieben werden, die die Thread-Klasse erweitert. |
beitreten() | Es blockiert die Ausführung von anderem Code, bis der Thread, in dem die join () -Methode aufgerufen wurde, beendet wird. |
Hintergrundgeschichte: Die Thread-Klasse
Bevor Sie mit dem Codieren von Multithread-Programmen mithilfe des Threading-Moduls beginnen, müssen Sie sich mit der Thread-Klasse vertraut machen. Die Thread-Klasse ist die primäre Klasse, die die Vorlage und die Operationen eines Threads in Python definiert.
Die häufigste Methode zum Erstellen einer Multithread-Python-Anwendung besteht darin, eine Klasse zu deklarieren, die die Thread-Klasse erweitert und ihre run () -Methode überschreibt.
Die Thread-Klasse bezeichnet zusammenfassend eine Codesequenz, die in einem separaten Steuerelement- Thread ausgeführt wird .
Wenn Sie also eine Multithread-App schreiben, gehen Sie wie folgt vor:
- Definieren Sie eine Klasse, die die Thread-Klasse erweitert
- Überschreiben Sie die __init__ Konstruktor
- Überschreiben Sie die run () -Methode
Sobald ein Thread-Objekt erstellt wurde, kann die start () -Methode verwendet werden, um die Ausführung dieser Aktivität zu starten, und die join () -Methode kann verwendet werden, um den gesamten anderen Code zu blockieren, bis die aktuelle Aktivität beendet ist.
Versuchen wir nun, das Threading-Modul zu verwenden, um Ihr vorheriges Beispiel zu implementieren. Starten Sie erneut Ihren IDLE und geben Sie Folgendes ein:
import timeimport threadingclass threadtester (threading.Thread):def __init__(self, id, name, i):threading.Thread.__init__(self)self.id = idself.name = nameself.i = idef run(self):thread_test(self.name, self.i, 5)print ("%s has finished execution " %self.name)def thread_test(name, wait, i):while i:time.sleep(wait)print ("Running %s \n" %name)i = i - 1if __name__=="__main__":thread1 = threadtester(1, "First Thread", 1)thread2 = threadtester(2, "Second Thread", 2)thread3 = threadtester(3, "Third Thread", 3)thread1.start()thread2.start()thread3.start()thread1.join()thread2.join()thread3.join()
Dies ist die Ausgabe, wenn Sie den obigen Code ausführen:
CODE ERKLÄRUNG
- Dieser Teil ist der gleiche wie in unserem vorherigen Beispiel. Hier importieren Sie das Zeit- und Thread-Modul, mit dem die Ausführung und Verzögerungen der Python-Threads behandelt werden.
- In diesem Bit erstellen Sie eine Klasse namens Threadtester, die die Thread- Klasse des Threading-Moduls erbt oder erweitert . Dies ist eine der häufigsten Methoden zum Erstellen von Threads in Python. Sie sollten jedoch nur den Konstruktor und die run () -Methode in Ihrer App überschreiben . Wie Sie im obigen Codebeispiel sehen können, wurde die Methode __init__ (Konstruktor) überschrieben.
In ähnlicher Weise haben Sie auch die run () -Methode überschrieben . Es enthält den Code, den Sie in einem Thread ausführen möchten. In diesem Beispiel haben Sie die Funktion thread_test () aufgerufen.
- Dies ist die thread_test () -Methode, die den Wert von i als Argument verwendet, ihn bei jeder Iteration um 1 verringert und den Rest des Codes durchläuft, bis i 0 wird. In jeder Iteration wird der Name des aktuell ausgeführten Threads gedruckt und schläft für Sekunden (was auch als Argument genommen wird).
- thread1 = threadtester (1, "Erster Thread", 1)
Hier erstellen wir einen Thread und übergeben die drei Parameter, die wir in __init__ deklariert haben. Der erste Parameter ist die ID des Threads, der zweite Parameter ist der Name des Threads und der dritte Parameter ist der Zähler, der bestimmt, wie oft die while-Schleife ausgeführt werden soll.
- thread2.start ()
Die Startmethode wird verwendet, um die Ausführung eines Threads zu starten. Intern ruft die Funktion start () die Methode run () Ihrer Klasse auf.
- thread3.join ()
Die join () -Methode blockiert die Ausführung von anderem Code und wartet, bis der Thread, auf dem er aufgerufen wurde, beendet ist.
Wie Sie bereits wissen, haben die Threads, die sich im selben Prozess befinden, Zugriff auf den Speicher und die Daten dieses Prozesses. Wenn mehr als ein Thread gleichzeitig versucht, die Daten zu ändern oder darauf zuzugreifen, können sich daher Fehler einschleichen.
Im nächsten Abschnitt sehen Sie die verschiedenen Arten von Komplikationen, die auftreten können, wenn Threads auf Daten und kritische Abschnitte zugreifen, ohne nach vorhandenen Zugriffstransaktionen zu suchen.
Deadlocks und Rennbedingungen
Bevor Sie sich mit Deadlocks und Rennbedingungen vertraut machen, sollten Sie einige grundlegende Definitionen im Zusammenhang mit der gleichzeitigen Programmierung verstehen:
- Kritischer Abschnitt
Es ist ein Codefragment, das auf gemeinsam genutzte Variablen zugreift oder diese ändert und als atomare Transaktion ausgeführt werden muss.
- Kontextwechsel
Es ist der Prozess, dem eine CPU folgt, um den Status eines Threads zu speichern, bevor er von einer Aufgabe zu einer anderen wechselt, damit er später an derselben Stelle wieder aufgenommen werden kann.
Deadlocks
Deadlocks sind das am meisten gefürchtete Problem, mit dem Entwickler beim Schreiben von gleichzeitigen / Multithread-Anwendungen in Python konfrontiert sind. Der beste Weg, um Deadlocks zu verstehen, ist die Verwendung des klassischen Beispielproblems der Informatik, das als Dining Philosophers Problem bekannt ist.
Die Problemstellung für Speisephilosophen lautet wie folgt:
Fünf Philosophen sitzen auf einem runden Tisch mit fünf Spaghetti-Tellern (eine Art Pasta) und fünf Gabeln, wie in der Abbildung gezeigt.

Zu jeder Zeit muss ein Philosoph entweder essen oder nachdenken.
Außerdem muss ein Philosoph die beiden neben ihm liegenden Gabeln (dh die linke und die rechte Gabel) nehmen, bevor er die Spaghetti essen kann. Das Problem des Deadlocks tritt auf, wenn alle fünf Philosophen gleichzeitig ihre rechten Gabeln aufheben.
Da jeder der Philosophen eine Gabel hat, werden alle darauf warten, dass die anderen ihre Gabel ablegen. Infolgedessen kann keiner von ihnen Spaghetti essen.
In ähnlicher Weise tritt in einem gleichzeitigen System ein Deadlock auf, wenn verschiedene Threads oder Prozesse (Philosophen) gleichzeitig versuchen, die gemeinsam genutzten Systemressourcen (Gabeln) abzurufen. Infolgedessen kann keiner der Prozesse ausgeführt werden, da er auf eine andere Ressource wartet, die von einem anderen Prozess gehalten wird.
Rennbedingungen
Eine Racebedingung ist ein unerwünschter Zustand eines Programms, der auftritt, wenn ein System zwei oder mehr Operationen gleichzeitig ausführt. Betrachten Sie zum Beispiel diese einfache for-Schleife:
i=0; # a global variablefor x in range(100):print(i)i+=1;
Wenn Sie n Threads erstellen, die diesen Code gleichzeitig ausführen, können Sie den Wert von i (der von den Threads gemeinsam genutzt wird) nicht bestimmen, wenn das Programm die Ausführung beendet hat. Dies liegt daran, dass sich in einer realen Multithreading-Umgebung die Threads überlappen können und sich der Wert von i, der von einem Thread abgerufen und geändert wurde, zwischendurch ändern kann, wenn ein anderer Thread darauf zugreift.
Dies sind die beiden Hauptklassen von Problemen, die in einer Multithread- oder verteilten Python-Anwendung auftreten können. Im nächsten Abschnitt erfahren Sie, wie Sie dieses Problem durch Synchronisieren von Threads beheben können.
Threads synchronisieren
Um mit Race-Bedingungen, Deadlocks und anderen Thread-basierten Problemen umzugehen, stellt das Threading-Modul das Lock- Objekt bereit . Die Idee ist, dass ein Thread, der Zugriff auf eine bestimmte Ressource wünscht, eine Sperre für diese Ressource erhält. Sobald ein Thread eine bestimmte Ressource sperrt, kann kein anderer Thread darauf zugreifen, bis die Sperre aufgehoben wird. Infolgedessen sind die Änderungen an der Ressource atomar und die Rennbedingungen werden abgewendet.
Eine Sperre ist ein Synchronisationsprimitiv auf niedriger Ebene, das vom __thread- Modul implementiert wird . Zu jedem Zeitpunkt kann sich eine Sperre in einem von zwei Zuständen befinden: gesperrt oder entsperrt. Es werden zwei Methoden unterstützt:
- erwerben()
Wenn der Sperrstatus entsperrt ist, ändert der Aufruf der Methode purchase () den Status in gesperrt und kehrt zurück. Wenn der Status jedoch gesperrt ist, wird der Aufruf von purchase () blockiert, bis die release () -Methode von einem anderen Thread aufgerufen wird.
- Veröffentlichung()
Die release () -Methode wird verwendet, um den Status auf entsperrt zu setzen, dh um eine Sperre aufzuheben. Es kann von jedem Thread aufgerufen werden, nicht unbedingt von dem, der die Sperre erhalten hat.
Hier ist ein Beispiel für die Verwendung von Sperren in Ihren Apps. Starten Sie Ihren IDLE und geben Sie Folgendes ein:
import threadinglock = threading.Lock()def first_function():for i in range(5):lock.acquire()print ('lock acquired')print ('Executing the first funcion')lock.release()def second_function():for i in range(5):lock.acquire()print ('lock acquired')print ('Executing the second funcion')lock.release()if __name__=="__main__":thread_one = threading.Thread(target=first_function)thread_two = threading.Thread(target=second_function)thread_one.start()thread_two.start()thread_one.join()thread_two.join()
Drücken Sie jetzt F5. Sie sollten eine Ausgabe wie diese sehen:
CODE ERKLÄRUNG
- Hier erstellen Sie einfach eine neue Sperre, indem Sie die Factory-Funktion threading.Lock () aufrufen . Intern gibt Lock () eine Instanz der effektivsten konkreten Lock-Klasse zurück, die von der Plattform verwaltet wird.
- In der ersten Anweisung erwerben Sie die Sperre, indem Sie die Methode purchase () aufrufen. Wenn die Sperre gewährt wurde, drucken Sie "Sperre erworben" auf die Konsole. Sobald der gesamte Code, den der Thread ausführen soll, die Ausführung abgeschlossen hat, heben Sie die Sperre auf, indem Sie die release () -Methode aufrufen.
Die Theorie ist in Ordnung, aber woher wissen Sie, dass das Schloss wirklich funktioniert hat? Wenn Sie sich die Ausgabe ansehen, werden Sie feststellen, dass jede der Druckanweisungen jeweils genau eine Zeile druckt. Denken Sie daran, dass in einem früheren Beispiel die Ausgaben von print zufällig waren, da mehrere Threads gleichzeitig auf die print () -Methode zugegriffen haben. Hier wird die Druckfunktion erst aufgerufen, nachdem die Sperre erlangt wurde. Die Ausgänge werden also einzeln und zeilenweise angezeigt.
Abgesehen von Sperren unterstützt Python auch einige andere Mechanismen zur Handhabung der Thread-Synchronisation, wie unten aufgeführt:
- RLocks
- Semaphoren
- Bedingungen
- Ereignisse und
- Barrieren
Global Interpreter Lock (und wie man damit umgeht)
Bevor wir uns mit den Details von Pythons GIL befassen, definieren wir einige Begriffe, die für das Verständnis des nächsten Abschnitts hilfreich sind:
- CPU-gebundener Code: Dies bezieht sich auf jeden Code, der direkt von der CPU ausgeführt wird.
- E / A-gebundener Code: Dies kann jeder Code sein, der über das Betriebssystem auf das Dateisystem zugreift
- CPython: es ist die Referenz Umsetzung von Python und kann als die in C und Python (Programmiersprache) geschriebenen Interpreters beschrieben.
Was ist GIL in Python?
Die globale Interpreter-Sperre (GIL) in Python ist eine Prozesssperre oder ein Mutex, der beim Umgang mit den Prozessen verwendet wird. Es stellt sicher, dass jeweils ein Thread auf eine bestimmte Ressource zugreifen kann, und verhindert außerdem die gleichzeitige Verwendung von Objekten und Bytecodes. Dies kommt den Single-Thread-Programmen bei einer Leistungssteigerung zugute. GIL in Python ist sehr einfach und leicht zu implementieren.
Eine Sperre kann verwendet werden, um sicherzustellen, dass zu einem bestimmten Zeitpunkt nur ein Thread Zugriff auf eine bestimmte Ressource hat.
Eine der Funktionen von Python besteht darin, dass für jeden Interpreter-Prozess eine globale Sperre verwendet wird. Dies bedeutet, dass jeder Prozess den Python-Interpreter selbst als Ressource behandelt.
Angenommen, Sie haben ein Python-Programm geschrieben, das zwei Threads verwendet, um sowohl CPU- als auch E / A-Operationen auszuführen. Wenn Sie dieses Programm ausführen, geschieht Folgendes:
- Der Python-Interpreter erstellt einen neuen Prozess und erzeugt die Threads
- Wenn Thread-1 gestartet wird, erfasst er zuerst die GIL und sperrt sie.
- Wenn Thread-2 jetzt ausgeführt werden soll, muss er warten, bis die GIL freigegeben wird, auch wenn ein anderer Prozessor frei ist.
- Angenommen, Thread-1 wartet auf eine E / A-Operation. Zu diesem Zeitpunkt wird die GIL freigegeben und Thread-2 wird sie erwerben.
- Wenn Thread-1 nach Abschluss der E / A-Operationen jetzt ausgeführt werden soll, muss er erneut warten, bis die GIL von Thread-2 freigegeben wird.
Aus diesem Grund kann immer nur ein Thread auf den Interpreter zugreifen, was bedeutet, dass zu einem bestimmten Zeitpunkt nur ein Thread Python-Code ausführt.
Dies ist in einem Single-Core-Prozessor in Ordnung, da für die Verarbeitung der Threads Time Slicing (siehe erster Abschnitt dieses Lernprogramms) verwendet wird. Bei Mehrkernprozessoren hat eine CPU-gebundene Funktion, die auf mehreren Threads ausgeführt wird, jedoch erhebliche Auswirkungen auf die Effizienz des Programms, da nicht alle verfügbaren Kerne gleichzeitig verwendet werden.
Warum wurde GIL gebraucht?
Der CPython-Garbage Collector verwendet eine effiziente Speicherverwaltungstechnik, die als Referenzzählung bezeichnet wird. So funktioniert es: Jedes Objekt in Python verfügt über eine Referenzanzahl, die erhöht wird, wenn es einem neuen Variablennamen zugewiesen oder einem Container hinzugefügt wird (z. B. Tupel, Listen usw.). Ebenso wird die Referenzanzahl verringert, wenn die Referenz den Gültigkeitsbereich verlässt oder wenn die del-Anweisung aufgerufen wird. Wenn der Referenzzähler eines Objekts 0 erreicht, wird der Müll gesammelt und der zugewiesene Speicher wird freigegeben.
Das Problem ist jedoch, dass die Referenzzählvariable wie jede andere globale Variable für Rennbedingungen anfällig ist. Um dieses Problem zu lösen, haben sich die Entwickler von Python für die Verwendung der globalen Interpretersperre entschieden. Die andere Option bestand darin, jedem Objekt eine Sperre hinzuzufügen, die zu Deadlocks und erhöhtem Overhead durch Aufrufe von purchase () und release () geführt hätte.
Daher ist GIL eine erhebliche Einschränkung für Multithread-Python-Programme, die schwere CPU-gebundene Operationen ausführen (wodurch sie effektiv Single-Threaded werden). Wenn Sie mehrere CPU-Kerne in Ihrer Anwendung verwenden möchten, verwenden Sie stattdessen das Multiprozessor- Modul.
Zusammenfassung
- Python unterstützt 2 Module für Multithreading:
- __thread- Modul: Es bietet eine Implementierung auf niedriger Ebene für das Threading und ist veraltet.
- Threading-Modul : Es bietet eine allgemeine Implementierung für Multithreading und ist der aktuelle Standard.
- Um einen Thread mit dem Threading-Modul zu erstellen, müssen Sie Folgendes tun:
- Erstellen Sie eine Klasse, die die Thread- Klasse erweitert.
- Überschreiben Sie den Konstruktor (__init__).
- Überschreiben Sie die run () -Methode.
- Erstellen Sie ein Objekt dieser Klasse.
- Ein Thread kann durch Aufrufen der Methode start () ausgeführt werden.
- Die join () -Methode kann verwendet werden, um andere Threads zu blockieren, bis dieser Thread (derjenige, auf dem der Join aufgerufen wurde) die Ausführung beendet.
- Eine Race-Bedingung tritt auf, wenn mehrere Threads gleichzeitig auf eine gemeinsam genutzte Ressource zugreifen oder diese ändern.
- Dies kann durch Synchronisieren von Threads vermieden werden.
- Python unterstützt 6 Möglichkeiten zum Synchronisieren von Threads:
- Schlösser
- RLocks
- Semaphoren
- Bedingungen
- Ereignisse und
- Barrieren
- Sperren erlauben nur einem bestimmten Thread, der die Sperre erhalten hat, den kritischen Abschnitt zu betreten.
- Ein Schloss hat zwei Hauptmethoden:
- purchase () : Setzt den Sperrstatus auf gesperrt. Wenn ein gesperrtes Objekt aufgerufen wird, wird es blockiert, bis die Ressource frei ist.
- release () : Setzt den Sperrstatus auf entsperrt und kehrt zurück. Wenn ein entsperrtes Objekt aufgerufen wird, wird false zurückgegeben.
- Die globale Interpreter-Sperre ist ein Mechanismus, über den jeweils nur 1 CPython-Interpreter-Prozess ausgeführt werden kann.
- Es wurde verwendet, um die Referenzzählfunktion des Garbage Collector von CPythons zu vereinfachen.
- Um Python-Apps mit starken CPU-gebundenen Vorgängen zu erstellen, sollten Sie das Multiprocessing-Modul verwenden.