Multithreading in Python mit Beispiel:Lernen Sie GIL in Python
Mit der Programmiersprache Python können Sie Multiprocessing oder Multithreading verwenden. In diesem Tutorial erfahren Sie, wie Sie Multithread-Anwendungen in Python schreiben.
Was ist ein Thread?
Ein Thread ist eine Ausführungseinheit bei gleichzeitiger 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 Programm in Ausführung. Wenn Sie eine Anwendung auf Ihrem Computer starten (z. B. einen Browser oder Texteditor), erstellt das Betriebssystem einen Prozess.
Was ist Multithreading in Python?
Multithreading in Python Programmieren 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. Multi-Threads können einzeln ausgeführt werden, während sie ihre Prozessressourcen teilen. Der Zweck von Multithreading besteht darin, mehrere Tasks und Funktionszellen gleichzeitig auszuführen.
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
- Synchronisieren von Threads
- Was ist GIL?
- Warum wurde GIL benötigt?
Was ist Multiprocessing?
Multiprocessing ermöglicht es Ihnen, mehrere voneinander unabhängige Prozesse gleichzeitig auszuführen. Diese Prozesse teilen ihre Ressourcen nicht und kommunizieren über IPC.
Python-Multithreading vs. Multiprocessing
Betrachten Sie zum Verständnis von Prozessen und Threads dieses Szenario: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 nun laufende Instanz des Programms heißt Prozess.
Jeder Prozess besteht aus zwei grundlegenden Komponenten:
- Der Kodex
- Die Daten
Nun 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 Abschnitt des Prozesses vorstellen, der vom Betriebssystem separat ausgeführt werden kann.
Mit anderen Worten, es handelt sich um einen Strom von Anweisungen, die vom Betriebssystem unabhängig ausgeführt werden können. Threads innerhalb eines einzelnen Prozesses teilen sich die Daten dieses Prozesses und sind so konzipiert, dass sie zusammenarbeiten, um die Parallelität zu erleichtern.
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 Geschwindigkeit, Leistung und Rendering Ihrer Anwendung 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 Multithreaded Anwendungen mit Python. Es gibt zwei Hauptmodule, die verwendet werden können, um Threads in Python zu handhaben:
- Der Faden Modul und
- Das Einfädeln Modul
In Python gibt es jedoch auch eine sogenannte globale Interpretersperre (GIL). Es ermöglicht keinen großen Leistungsgewinn und kann sogar reduzieren die Leistung einiger Multithread-Anwendungen. 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 bezeichnet und ist nur noch als __thread zugänglich für Abwärtskompatibilität.
Sie sollten das übergeordnete Threading verwenden 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)
In Ordnung, jetzt haben Sie die grundlegende Theorie behandelt, um mit dem Programmieren zu beginnen. Öffnen Sie also Ihren 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, ist dies die Ausgabe, die Sie sehen sollten:
In den nächsten Abschnitten erfahren Sie mehr über Rennbedingungen und wie Sie damit umgehen
CODE-ERKLÄRUNG
- Diese Anweisungen importieren die Zeit- und Thread-Module, die verwendet werden, um die Ausführung und Verzögerung der Python-Threads zu handhaben.
- Hier haben Sie eine Funktion namens thread_test definiert die vom start_new_thread aufgerufen wird Methode. 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 Nachricht ausgegeben, die besagt, dass der Thread die Ausführung beendet hat.
- Dies ist der Hauptabschnitt Ihres Programms. Hier rufen Sie einfach den start_new_thread auf Methode mit dem thread_test Funktion als Argument. Dies erstellt einen neuen Thread für die Funktion, die Sie als Argument übergeben, und beginnt mit der Ausführung. Beachten Sie, dass Sie dies ersetzen können (thread_ test) mit jeder 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. Es bietet im Vergleich zum Thread-Modul eine große Auswahl an Funktionen.
Hier ist eine Liste einiger nützlicher Funktionen, die in diesem Modul definiert sind:
Funktionsname | Beschreibung |
---|---|
activeCount() | Gibt die Anzahl der Threads zurück Objekte, die noch leben |
aktuellerThread() | Gibt das aktuelle Objekt der Thread-Klasse zurück. |
aufzählen() | Listet alle aktiven Thread-Objekte auf. |
isDaemon() | Gibt wahr zurück, wenn der Thread ein Daemon ist. |
istAlive() | Gibt true zurück, wenn der Thread noch am Leben ist. |
Thread-Klassenmethoden | |
Start() | Startet die Aktivität eines Threads. Es muss nur einmal für jeden Thread aufgerufen werden, da es einen Laufzeitfehler auslöst, wenn es mehrmals aufgerufen wird. |
run() | 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 Methode join() aufgerufen wurde, beendet wird. |
Hintergrundgeschichte:Die Thread-Klasse
Bevor Sie mit dem Codieren von Multithreading-Programmen mit dem Threading-Modul beginnen, ist es wichtig, die Thread-Klasse zu verstehen. Die Thread-Klasse ist die primäre Klasse, die die Vorlage und die Operationen eines Threads in Python definiert.
Die gebräuchlichste Art, eine Multithread-Python-Anwendung zu erstellen, besteht darin, eine Klasse zu deklarieren, die die Thread-Klasse erweitert und ihre run()-Methode überschreibt.
Zusammenfassend bezeichnet die Thread-Klasse eine Codesequenz, die in einem separaten Thread ausgeführt wird der Kontrolle.
Wenn Sie also eine Multithread-App schreiben, gehen Sie wie folgt vor:
- definiere eine Klasse, die die Thread-Klasse erweitert
- Überschreiben Sie die __init__ Konstruktor
- Überschreiben Sie run() Methode
Sobald ein Thread-Objekt erstellt wurde, wird der start() -Methode kann verwendet werden, um die Ausführung dieser Aktivität und des join() zu starten -Methode kann verwendet werden, um den gesamten anderen Code zu blockieren, bis die aktuelle Aktivität beendet ist.
Lassen Sie uns nun versuchen, das Threading-Modul zu verwenden, um Ihr vorheriges Beispiel zu implementieren. Starten Sie erneut Ihren 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 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 die Zeit- und Thread-Module, die verwendet werden, um die Ausführung und Verzögerungen der Python-Threads zu handhaben.
- In diesem Bit erstellen Sie eine Klasse namens Threadtester, die den Thread erbt oder erweitert Klasse des Threading-Moduls. Dies ist eine der häufigsten Methoden zum Erstellen von Threads in Python. Sie sollten jedoch nur den Konstruktor und den run() überschreiben Methode in Ihrer App. Wie Sie im obigen Codebeispiel sehen können, ist die __init__ Methode (Konstruktor) wurde überschrieben. Ebenso haben Sie auch run() überschrieben Methode. 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 Methode thread_test(), die den Wert von i annimmt als Argument, verringert es bei jeder Iteration um 1 und durchläuft den Rest des Codes, bis i 0 wird. Bei 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, „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 Methode start 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, 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 also mehr als ein Thread gleichzeitig versucht, 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 auf vorhandene Zugriffstransaktionen zu prüfen.
Deadlocks und Rennbedingungen
Bevor Sie etwas über Deadlocks und Race Conditions lernen, ist es hilfreich, einige grundlegende Definitionen im Zusammenhang mit gleichzeitiger Programmierung zu verstehen:
- Kritischer AbschnittEs ist ein Codefragment, das auf gemeinsam genutzte Variablen zugreift oder diese ändert und als atomare Transaktion ausgeführt werden muss.
- Context SwitchIt ist der Prozess, dem eine CPU folgt, um den Status eines Threads zu speichern, bevor sie von einer Aufgabe zu einer anderen wechselt, damit sie später an derselben Stelle fortgesetzt werden kann.
Deadlocks
Deadlocks sind das am meisten gefürchtete Problem, mit dem Entwickler konfrontiert sind, wenn sie gleichzeitige/multithreaded Anwendungen in Python schreiben. 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 an einem runden Tisch mit fünf Tellern Spaghetti (einer Nudelsorte) und fünf Gabeln, wie in der Abbildung gezeigt.
Python
- free()-Funktion in der C-Bibliothek:Wie verwenden? Lernen Sie mit Beispiel
- Python String strip() Funktion mit BEISPIEL
- Python String count() mit BEISPIELE
- Python-Funktion round() mit BEISPIELE
- Python map() Funktion mit BEISPIELE
- Python Timeit() mit Beispielen
- Python-Zähler in Sammlungen mit Beispiel
- Python List count() mit BEISPIELE
- Python List index() mit Beispiel
- C# – Multithreading