Multithreading in Python mit Beispiel: Lernen Sie GIL in Python
Was ist ein Faden?
Ein Thread ist eine Ausfรผhrungseinheit fรผr die gleichzeitige Programmierung. Multithreading ist eine Technik, die es einer CPU ermรถglicht, viele Aufgaben eines Prozesses gleichzeitig auszufรผhren. Diese Threads kรถnnen einzeln ausgefรผhrt werden, wรคhrend sie ihre Prozessressourcen gemeinsam nutzen.
Was ist ein Prozess?
Ein Prozess ist im Grunde das ausgefรผhrte Programm. Wenn Sie eine Anwendung auf Ihrem Computer starten (z. B. einen Browser oder einen Texteditor), erstellt das Betriebssystem einen
Was ist Multithreading in Python?
Multithreading in Python Programmierung ist eine bekannte Technik, bei der mehrere Threads in einem Prozess ihren Datenraum mit dem Haupt-Thread teilen, was den Informationsaustausch und die Kommunikation innerhalb von Threads einfach und effizient macht. Threads sind leichter als Prozesse. Mehrere Threads kรถnnen einzeln ausgefรผhrt werden, wรคhrend sie ihre Prozessressourcen gemeinsam nutzen. Der Zweck von Multithreading besteht darin, mehrere Aufgaben und Funktionszellen gleichzeitig auszufรผhren.
Was ist Multiprocessing?
Multiprozessing ermรถglicht Ihnen, mehrere unabhรคngige Prozesse gleichzeitig auszufรผhren. Diese Prozesse teilen ihre Ressourcen nicht und kommunizieren รผber IPC.
Python Multithreading vs. Multiprocessing
Um Prozesse und Threads zu verstehen, stellen Sie sich dieses Szenario vor: 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, die gerade ausgefรผhrt wird, wird als Prozess bezeichnet.
Jeder Prozess besteht aus zwei grundlegenden Komponenten:
- Der Code des Chamรคleons
- Die Fakten
Nun kann ein Prozess einen oder mehrere aufgerufene Unterteile enthalten Threads. Dies hรคngt von der Betriebssystemarchitektur ab. Sie kรถnnen sich einen Thread als einen Abschnitt des Prozesses vorstellen, der vom Betriebssystem separat ausgefรผhrt werden kann.
Mit anderen Worten handelt es 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 Parallelitรคt zu ermรถglichen.
Warum Multithreading verwenden?
Mit Multithreading kรถnnen Sie eine Anwendung in mehrere Unteraufgaben aufteilen und diese Aufgaben gleichzeitig ausfรผhren. Wenn Sie Multithreading richtig verwenden, kรถnnen Sie die Geschwindigkeit, Leistung und Darstellung Ihrer Anwendung verbessern.
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 Multithreading Anwendungen mit Python. Es gibt zwei Hauptmodule, die zum Verarbeiten von Threads in Python:
- Die Faden Modul und
- Die einfรคdeln Modulen
In Python gibt es jedoch auch eine sogenannte globale Interpretersperre (GIL). Es ermรถglicht keinen groรen Leistungszuwachs, vielleicht sogar Veteran die Leistung einiger Multithread-Anwendungen. Alles darรผber erfahren Sie in den nรคchsten Abschnitten dieses Tutorials.
Die Thread- und Threading-Module
Die beiden Module, die Sie in diesem Tutorial kennenlernen werden, sind: Thread-Modul und der Threading-Modul.
Das Thread-Modul ist jedoch schon lange veraltet. Beginnend mit Python 3, es wurde als veraltet gekennzeichnet und ist nur zugรคnglich als __Gewinde fรผr Abwรคrtskompatibilitรคt.
Sie sollten die hรถhere Ebene verwenden einfรคdeln Modul fรผr Anwendungen, 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. Also, รถffnen Sie Ihr IDLE oder einen Notizblock und geben Sie Folgendes ein:
import time
import _thread
def thread_test(name, wait):
i = 0
while i <= 3:
time.sleep(wait)
print("Running %s\n" %name)
i = i + 1
print("%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, sollten Sie folgende Ausgabe sehen:
In den nรคchsten Abschnitten erfahren Sie mehr รผber die Rennbedingungen und deren Handhabung
CODE-ERKLรRUNG
- Diese Anweisungen importieren das Zeit- und Threadmodul, das fรผr die Ausfรผhrung und Verzรถgerung des Python Threads.
- Hier haben Sie eine Funktion namens definiert thread_test, welches von der aufgerufen wird start_new_thread Methode. Die Funktion fรผhrt vier Iterationen lang eine While-Schleife aus und gibt den Namen des Threads aus, der sie aufgerufen hat. Sobald die Iteration abgeschlossen ist, wird eine Meldung ausgegeben, die besagt, dass die Ausfรผhrung des Threads abgeschlossen ist.
- Dies ist der Hauptabschnitt Ihres Programms. Hier rufen Sie einfach die an start_new_thread Methode mit der thread_test Funktion als Argument. Dadurch wird ein neuer Thread fรผr die Funktion, die Sie als Argument รผbergeben, erstellt und mit der Ausfรผhrung begonnen. Beachten Sie, dass Sie dies ersetzen kรถnnen (Thread_test) mit einer anderen Funktion, die Sie als Thread ausfรผhren mรถchten.
Das Threading-Modul
Dieses Modul ist die High-Level-Implementierung von Threading in Python und der De-facto-Standard fรผr die Verwaltung von Multithread-Anwendungen. Im Vergleich zum Thread-Modul bietet es eine Vielzahl von Funktionen.

Hier ist eine Liste einiger nรผtzlicher Funktionen, die in diesem Modul definiert sind:
| Funktionsname | Beschreibung |
|---|---|
| activeCount() | Gibt die Anzahl von zurรผck Thread Objekte, die noch am Leben sind |
| aktuellerThread() | 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. |
| Methoden der Thread-Klasse | |
| Start() | Startet die Aktivitรคt eines Threads. Es darf fรผr jeden Thread nur einmal 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 anderen Codes, bis der Thread, fรผr den die Methode join() aufgerufen wurde, beendet wird. |
Hintergrundgeschichte: Die Thread-Klasse
Bevor Sie mit der Codierung von Multithread-Programmen unter Verwendung des Threading-Moduls beginnen, ist es wichtig, dass Sie die Thread-Klasse verstehen. Die Thread-Klasse ist die primรคre Klasse, die die Vorlage und die Operationen eines Threads in Python definiert.
Die gebrรคuchlichste Methode zum Erstellen einer Multithread-Python-Anwendung besteht darin, eine Klasse zu deklarieren, die die Thread-Klasse erweitert und deren run()-Methode รผberschreibt.
Zusammenfassend stellt die Thread-Klasse eine Codesequenz dar, die separat ausgefรผhrt wird Faden der Kontrolle.
Wenn Sie eine Multithread-App schreiben, gehen Sie also wie folgt vor:
- Definieren Sie eine Klasse, die die Thread-Klasse erweitert
- รberschreiben Sie die __init__ Konstruktor
- รberschreiben Sie die Lauf() Methode
Sobald ein Thread-Objekt erstellt wurde, wird das Start() Mit der Methode kann mit der Ausfรผhrung dieser Aktivitรคt begonnen werden beitreten() Die Methode kann verwendet werden, um den gesamten anderen Code zu blockieren, bis die aktuelle Aktivitรคt beendet ist.
Versuchen wir nun, das Threading-Modul zur Implementierung Ihres vorherigen Beispiels zu verwenden. Starten Sie noch einmal Ihr IDLE und geben Sie Folgendes ein:
import time
import threading
class threadtester (threading.Thread):
def __init__(self, id, name, i):
threading.Thread.__init__(self)
self.id = id
self.name = name
self.i = i
def 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 - 1
if __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 wird die Ausgabe sein, wenn Sie den obigen Code ausfรผhren:
CODE-ERKLรRUNG
- Dieser Teil ist derselbe wie in unserem vorherigen Beispiel. Hier importieren Sie das Zeit- und Thread-Modul, die fรผr die Ausfรผhrung und Verzรถgerungen des Python Threads.
- In diesem Teil erstellen Sie eine Klasse namens Threadtester, die die Klasse erbt oder erweitert Thread Klasse des Threading-Moduls. Dies ist eine der gebrรคuchlichsten Methoden zum Erstellen von Threads in Python. Sie sollten jedoch nur den Konstruktor und die รผberschreiben Lauf() Methode in Ihrer App. Wie Sie im obigen Codebeispiel sehen kรถnnen, ist die __init__ Methode (Konstruktor) wurde รผberschrieben. Ebenso haben Sie auch das รผberschrieben Lauf() Methode. Es enthรคlt den Code, den Sie innerhalb eines Threads ausfรผhren mรถchten. In diesem Beispiel haben Sie die Funktion thread_test() aufgerufen.
- Dies ist die Methode thread_test(), die den Wert von annimmt i als Argument, verringert es bei jeder Iteration um 1 und durchlรคuft den Rest des Codes, bis i 0 wird. In jeder Iteration gibt es den Namen des aktuell ausgefรผhrten Threads aus und schlรคft fรผr Wartesekunden (was auch als Argument verwendet wird). ).
- thread1 = threadtester(1, โFirst 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()D 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 Methode join() blockiert die Ausfรผhrung anderen Codes und wartet, bis der Thread, in dem sie 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 daher mehrere Threads gleichzeitig versuchen, die Daten zu รคndern oder darauf zuzugreifen, kรถnnen sich 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 Race Conditions
Bevor wir uns mit Deadlocks und Race Conditions befassen, ist es hilfreich, einige grundlegende Definitionen im Zusammenhang mit paralleler Programmierung zu verstehen:
- Kritischer Abschnitt: Dies ist ein Codefragment, das auf gemeinsam genutzte Variablen zugreift oder diese รคndert und als atomare Transaktion ausgefรผhrt werden muss.
- Kontextwechsel: Dies ist der Vorgang, den eine CPU durchfรผhrt, um den Status eines Threads zu speichern, bevor von einer Aufgabe zu einer anderen gewechselt wird, sodass er spรคter an derselben Stelle fortgesetzt werden kann.
Blockaden
Blockaden sind das am meisten gefรผrchtete Problem, mit dem Entwickler konfrontiert werden, wenn sie gleichzeitige/multithreaded Anwendungen in Python schreiben. Deadlocks lassen sich am besten anhand des klassischen Beispielproblems der Informatik verstehen, das als Restaurants PhiloSophers Problem.
Die Problemstellung fรผr speisende Philosophen lautet wie folgt:
Fรผnf Philosophen sitzen an einem runden Tisch mit fรผnf Tellern Spaghetti (eine Nudelsorte) und fรผnf Gabeln, wie in der Abbildung dargestellt.
Ein Philosoph muss zu jeder Zeit entweder essen oder nachdenken.
Darรผber hinaus muss ein Philosoph die beiden Gabeln neben ihm nehmen (also die linke und die rechte Gabel), bevor er die Spaghetti essen kann. Das Deadlock-Problem tritt auf, wenn alle fรผnf Philosophen gleichzeitig ihre rechte Gabel nehmen.
Da jeder der Philosophen eine Gabel hat, werden sie alle warten, bis die anderen ihre Gabeln hinlegen. Infolgedessen wird keiner von ihnen Spaghetti essen kรถnnen.
รhnlich verhรคlt es sich in einem parallelen System: Ein Deadlock tritt auf, wenn verschiedene Threads oder Prozesse (Philosophen) gleichzeitig versuchen, die gemeinsam genutzten Systemressourcen (Forks) zu beanspruchen. Dies fรผhrt dazu, dass keiner der Prozesse ausgefรผhrt werden kann, da sie auf eine andere Ressource warten, die von einem anderen Prozess gehalten wird.
Rennbedingungen
Ein Race Condition ist ein unerwรผnschter Zustand eines Programms, der auftritt, wenn ein System zwei oder mehr Operationen gleichzeitig ausfรผhrt. Betrachten Sie beispielsweise diese einfache for-Schleife:
i=0; # a global variable
for x in range(100):
print(i)
i+=1;
Wenn Sie erstellen n Anzahl der Threads, 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. Dies liegt daran, dass sich die Threads in einer echten Multithreading-Umgebung รผ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 Haupttypen von Problemen, die in einer Multithread- oder verteilten Python-Anwendung auftreten kรถnnen. Im nรคchsten Abschnitt erfahren Sie, wie Sie dieses Problem durch die Synchronisierung von Threads lรถsen kรถnnen.
Syncchronisierende Threads
Um mit Race Conditions, Deadlocks und anderen Thread-basierten Problemen umzugehen, bietet das Threading-Modul die Zahnscheiben Objekt. Die Idee ist, dass ein Thread, wenn er auf eine bestimmte Ressource zugreifen mรถchte, 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. Dadurch werden die รnderungen an der Ressource atomar und Race Conditions werden vermieden.
Eine Sperre ist ein Synchronisierungsprimitiv auf niedriger Ebene, das von der __Gewinde Modul. Eine Sperre kann sich jederzeit in einem von zwei Zustรคnden befinden: verschlossen or entsperrt. Es unterstรผtzt zwei Methoden:
- erwerben()Wenn der Sperrzustand entsperrt ist, wird durch Aufrufen der Methode โacquire()โ der Zustand in โgesperrtโ geรคndert und zurรผckgegeben. Wenn der Status jedoch gesperrt ist, wird der Aufruf von acquire() blockiert, bis die Methode release() von einem anderen Thread aufgerufen wird.
- freigeben()Mit der Methode release() wird der Zustand auf โunlockedโ gesetzt, also eine Sperre aufgehoben. Es kann von jedem Thread aufgerufen werden, nicht unbedingt von dem Thread, der die Sperre erhalten hat.
Hier ist ein Beispiel fรผr die Verwendung von Sperren in Ihren Apps. Starten Sie Ihr IDLE und geben Sie Folgendes ein:
import threading
lock = 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 nun F5. Sie sollten eine Ausgabe wie diese sehen:
CODE-ERKLรRUNG
- Hier erstellen Sie einfach eine neue Sperre, indem Sie die aufrufen threading.Lock() Werksfunktion. Intern gibt Lock() eine Instanz der effektivsten konkreten Lock-Klasse zurรผck, die von der Plattform verwaltet wird.
- In der ersten Anweisung erhalten Sie die Sperre, indem Sie die Methode acquire() aufrufen. Wenn die Sperre erteilt wurde, drucken Sie โSperre erworbenโ zur Konsole. Sobald die Ausfรผhrung des gesamten Codes, den der Thread ausfรผhren soll, abgeschlossen ist, heben Sie die Sperre auf, indem Sie die Methode release() aufrufen.
Die Theorie ist gut, aber woher wissen Sie, dass die Sperre wirklich funktioniert hat? Wenn Sie sich die Ausgabe ansehen, werden Sie feststellen, dass jede der Druckanweisungen jeweils genau eine Zeile ausgibt. Erinnern Sie sich, dass in einem frรผheren Beispiel die Ausgaben von print zufรคllig waren, weil mehrere Threads gleichzeitig auf die Methode print() zugegriffen haben. Hier wird die Druckfunktion erst aufgerufen, nachdem die Sperre erhalten wurde. Die Ausgaben werden also einzeln und Zeile fรผr Zeile angezeigt.
Abgesehen von Sperren unterstรผtzt Python auch einige andere Mechanismen zur Handhabung der Thread-Synchronisierung, wie unten aufgefรผhrt:
- RLocks
- Semaphores
- Erkrankungen
- Veranstaltungen und
- Barriers
Global Interpreter Lock (und wie man damit umgeht)
Bevor wir uns mit den Details von Pythons GIL befassen, definieren wir einige Begriffe, die zum Verstรคndnis des nรคchsten Abschnitts hilfreich sind:
- CPU-gebundener Code: Dies bezieht sich auf jeden Codeabschnitt, 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 Implementierung of Python und kann als der in C geschriebene Interpreter beschrieben werden und Python (Programmiersprache).
Was ist GIL in Python?
Globale Dolmetschersperre (GIL) In Python wird eine Prozesssperre oder ein Mutex beim Umgang mit den Prozessen verwendet. 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-Threaded-Programmen in einer Leistungssteigerung zugute. GIL in Python ist sehr einfach und leicht zu implementieren.
Mit einer Sperre kann sichergestellt werden, dass zu einem bestimmten Zeitpunkt nur ein Thread Zugriff auf eine bestimmte Ressource hat.
Eines der Merkmale von Python besteht darin, dass fรผr jeden Interpreterprozess eine globale Sperre verwendet wird, was 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 I/O-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 mit der Ausfรผhrung beginnt, erfasst er zunรคchst die GIL und sperrt sie.
- Wenn Thread-2 jetzt ausgefรผhrt werden mรถchte, muss er auf die Freigabe der GIL warten, auch wenn ein anderer Prozessor frei ist.
- Nehmen wir nun an, dass Thread 1 auf eine E/A-Operation wartet. Zu diesem Zeitpunkt gibt er den GIL frei und Thread 2 holt ihn sich.
- Wenn Thread-1 nach Abschluss der E/A-Vorgรคnge jetzt ausgefรผhrt werden mรถchte, muss er erneut auf die Freigabe der GIL durch Thread-2 warten.
Aus diesem Grund kann jeweils nur ein Thread auf den Interpreter zugreifen, was bedeutet, dass es zu einem bestimmten Zeitpunkt nur einen Thread gibt, der Python-Code ausfรผhrt.
Dies ist in einem Single-Core-Prozessor in Ordnung, da fรผr die Verarbeitung der Threads Zeitscheiben (siehe den ersten Abschnitt dieses Tutorials) verwendet wรผrden. Bei Mehrkernprozessoren hat jedoch die Ausfรผhrung einer CPU-gebundenen Funktion in mehreren Threads erhebliche Auswirkungen auf die Effizienz des Programms, da nicht alle verfรผgbaren Kerne gleichzeitig genutzt werden.
Warum wurde GIL benรถtigt?
Die CPython Der Garbage Collector verwendet eine effiziente Speicherverwaltungstechnik, die als Referenzzรคhlung bekannt ist. So funktioniert es: Jedes Objekt in Python hat einen Referenzzรคhler, der erhรถht wird, wenn ihm ein neuer Variablenname zugewiesen oder es einem Container (wie Tupeln, Listen usw.) hinzugefรผgt wird. Ebenso wird der Referenzzรคhler verringert, wenn die Referenz den Gรผltigkeitsbereich verlรคsst oder wenn die Anweisung del aufgerufen wird. Wenn der Referenzzรคhler eines Objekts 0 erreicht, wird es einer Garbage Collection unterzogen und der zugewiesene Speicher wird freigegeben.
Das Problem besteht jedoch darin, dass die Referenzzรคhlvariable wie jede andere globale Variable anfรคllig fรผr Race Conditions ist. Um dieses Problem zu lรถsen, entschieden sich die Entwickler von Python, die globale Interpretersperre zu verwenden. Die andere Mรถglichkeit bestand darin, jedem Objekt eine Sperre hinzuzufรผgen, was zu Deadlocks und erhรถhtem Overhead durch acquire()- und release()-Aufrufe gefรผhrt hรคtte.
Daher stellt GIL eine erhebliche Einschrรคnkung fรผr Multithread-Python-Programme dar, die CPU-lastige Operationen ausfรผhren (und macht sie damit effektiv zu Singlethread-Programmen). Wenn Sie in Ihrer Anwendung mehrere CPU-Kerne nutzen mรถchten, verwenden Sie die Mehrfachverarbeitung Modul statt.
Zusammenfassung
- Python unterstรผtzt 2 Module fรผr Multithreading:
- __Gewinde Modul: Es bietet eine Low-Level-Implementierung fรผr Threading und ist veraltet.
- Threading-Modul: Es bietet eine High-Level-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 das erweitert Thread Klasse.
- รberschreiben Sie seinen Konstruktor (__init__).
- รberschreiben Sie es Lauf() Methode.
- Erstellen Sie ein Objekt dieser Klasse.
- Ein Thread kann durch Aufrufen von ausgefรผhrt werden Start() Methode.
- Die beitreten() Mit der Methode kรถnnen andere Threads blockiert werden, bis die Ausfรผhrung dieses Threads (der Thread, fรผr den Join aufgerufen wurde) abgeschlossen ist.
- Eine Race-Bedingung tritt auf, wenn mehrere Threads gleichzeitig auf eine gemeinsam genutzte Ressource zugreifen oder diese รคndern.
- Es kann vermieden werden durch Syncchronisierende Threads.
- Python unterstรผtzt 6 Mรถglichkeiten zum Synchronisieren von Threads:
- Schlรถsser
- RLocks
- Semaphores
- Erkrankungen
- Veranstaltungen und
- Barriers
- Sperren erlauben nur einem bestimmten Thread, der die Sperre erhalten hat, den Zugriff auf den kritischen Abschnitt.
- Eine Sperre verfรผgt รผber zwei Hauptmethoden:
- erwerben(): Der Sperrstatus wird auf gesetzt verschlossen. Wenn es fรผr ein gesperrtes Objekt aufgerufen wird, blockiert es, bis die Ressource frei ist.
- freigeben(): Der Sperrstatus wird auf gesetzt entriegelt und kehrt zurรผck. Wenn es fรผr ein entsperrtes Objekt aufgerufen wird, wird โfalseโ zurรผckgegeben.
- Die globale Interpretersperre ist ein Mechanismus, durch den nur 1 CPython Interpreterprozesse kรถnnen gleichzeitig ausgefรผhrt werden.
- Es wurde verwendet, um die Referenzzรคhlfunktion von C zu erleichternPythons' Garbage Collector.
- Um Python Apps mit intensiven CPU-intensiven Vorgรคngen sollten Sie das Multiprocessing-Modul verwenden.






