Python-Threading: Eine Einführung
Veröffentlicht: 2022-10-25In diesem Lernprogramm erfahren Sie, wie Sie das integrierte Threading -Modul von Python verwenden, um die Multithreading-Funktionen in Python zu erkunden.
Beginnend mit den Grundlagen von Prozessen und Threads lernen Sie, wie Multithreading in Python funktioniert, und verstehen gleichzeitig die Konzepte von Nebenläufigkeit und Parallelität. Anschließend erfahren Sie, wie Sie mithilfe des integrierten threading
-Moduls einen oder mehrere Threads in Python starten und ausführen.
Lass uns anfangen.
Prozesse vs. Threads: Was sind die Unterschiede?
Was ist ein Prozess?
Ein Prozess ist jede Instanz eines Programms, das ausgeführt werden muss.
Es kann alles sein – ein Python-Skript oder ein Webbrowser wie Chrome bis hin zu einer Videokonferenzanwendung. Wenn Sie den Task-Manager auf Ihrem Computer starten und zu Leistung –> CPU navigieren, können Sie die Prozesse und Threads sehen, die derzeit auf Ihren CPU-Kernen ausgeführt werden.

Prozesse und Threads verstehen
Intern hat ein Prozess einen dedizierten Speicher, der den Code und die Daten speichert, die dem Prozess entsprechen.
Ein Prozess besteht aus einem oder mehreren Threads . Ein Thread ist die kleinste Folge von Anweisungen, die das Betriebssystem ausführen kann, und stellt den Ausführungsfluss dar.
Jeder Thread hat seinen eigenen Stack und Register, aber keinen dedizierten Speicher. Alle einem Prozess zugeordneten Threads können auf die Daten zugreifen. Daher werden Daten und Speicher von allen Threads eines Prozesses gemeinsam genutzt.

In einer CPU mit N Kernen können N Prozesse zur selben Zeit parallel ausgeführt werden. Zwei Threads desselben Prozesses können jedoch niemals parallel ausgeführt werden, sondern können gleichzeitig ausgeführt werden. Wir werden uns im nächsten Abschnitt mit dem Konzept der Nebenläufigkeit vs. Parallelität befassen.
Lassen Sie uns basierend auf dem, was wir bisher gelernt haben, die Unterschiede zwischen einem Prozess und einem Thread zusammenfassen.
Feature | Verfahren | Faden |
Erinnerung | Dedizierte Erinnerung | Geteilte Erinnerung |
Art der Ausführung | Parallel, gleichzeitig | Gleichzeitig; aber nicht parallel |
Ausführung durchgeführt von | Betriebssystem | CPython-Interpreter |
Multithreading in Python
In Python stellt die Global Interpreter Lock (GIL) sicher, dass zu jedem Zeitpunkt nur ein Thread die Sperre erwerben und ausführen kann. Alle Threads sollten diese Sperre erwerben, um ausgeführt zu werden. Dadurch wird sichergestellt, dass zu einem bestimmten Zeitpunkt nur ein einziger Thread ausgeführt werden kann, und gleichzeitiges Multithreading wird vermieden.
Betrachten Sie beispielsweise zwei Threads, t1
und t2
, desselben Prozesses. Da Threads dieselben Daten gemeinsam nutzen, wenn t1
einen bestimmten Wert k
liest, kann t2
denselben Wert k
ändern. Dies kann zu Deadlocks und unerwünschten Ergebnissen führen. Aber nur einer der Threads kann die Sperre erwerben und in jeder Instanz ausgeführt werden. Daher sorgt GIL auch für Gewindesicherheit .
Wie erreichen wir also Multithreading-Fähigkeiten in Python? Um dies zu verstehen, wollen wir die Konzepte Parallelität und Parallelität diskutieren.
Nebenläufigkeit vs. Parallelität: Ein Überblick
Stellen Sie sich eine CPU mit mehr als einem Kern vor. In der Abbildung unten hat die CPU vier Kerne. Das bedeutet, dass wir zu jedem Zeitpunkt vier verschiedene Operationen parallel ausführen können.
Wenn es vier Prozesse gibt, kann jeder der Prozesse unabhängig und gleichzeitig auf jedem der vier Kerne laufen. Nehmen wir an, dass jeder Prozess zwei Threads hat.

Um zu verstehen, wie Threading funktioniert, wechseln wir von der Multicore- zur Singlecore-Prozessorarchitektur. Wie erwähnt, kann bei einer bestimmten Ausführungsinstanz nur ein einziger Thread aktiv sein; aber der Prozessorkern kann zwischen den Threads umschalten.

E/A-gebundene Threads warten beispielsweise häufig auf E/A-Operationen: Einlesen von Benutzereingaben, Datenbanklesevorgänge und Dateioperationen. Während dieser Wartezeit kann er die Sperre freigeben , damit der andere Thread ausgeführt werden kann. Die Wartezeit kann auch eine einfache Operation sein, wie z. B. Schlafen für n
Sekunden.
Zusammengefasst: Während Warteoperationen gibt der Thread die Sperre frei, wodurch der Prozessorkern auf einen anderen Thread umschalten kann. Der frühere Thread nimmt die Ausführung nach Ablauf der Wartezeit wieder auf. Dieser Prozess, bei dem der Prozessorkern gleichzeitig zwischen den Threads umschaltet, erleichtert Multithreading.
Wenn Sie Parallelität auf Prozessebene in Ihrer Anwendung implementieren möchten, sollten Sie stattdessen die Verwendung von Multiprocessing in Betracht ziehen.
Python-Threading-Modul: Erste Schritte
Python wird mit einem threading
-Modul geliefert, das Sie in das Python-Skript importieren können.
import threading
Um ein Thread-Objekt in Python zu erstellen, können Sie den Thread
-Konstruktor verwenden: threading.Thread(...)
. Dies ist die generische Syntax, die für die meisten Threading-Implementierungen ausreicht:
threading.Thread(target=...,args=...)
Hier,
-
target
ist das Schlüsselwortargument, das eine aufrufbare Python-Datei bezeichnet -
args
ist das Tupel von Argumenten, die das Ziel aufnimmt.
Sie benötigen Python 3.x, um die Codebeispiele in diesem Tutorial auszuführen. Laden Sie den Code herunter und folgen Sie ihm.
So definieren und führen Sie Threads in Python aus
Lassen Sie uns einen Thread definieren, der eine Zielfunktion ausführt.
Die Zielfunktion ist some_func
.
import threading import time def some_func(): print("Running some_func...") time.sleep(2) print("Finished running some_func.") thread1 = threading.Thread(target=some_func) thread1.start() print(threading.active_count())
Lassen Sie uns analysieren, was das obige Code-Snippet tut:

- Es importiert das
threading
und dietime
. - Die Funktion
some_func
hat beschreibendeprint()
Anweisungen und beinhaltet eine Schlafoperation für zwei Sekunden:time.sleep(n)
bewirkt, dass die Funktionn
Sekunden lang schläft. - Als nächstes definieren wir einen Thread
thread_1
mit dem Zielsome_func
.threading.Thread(target=...)
erstellt ein Thread-Objekt. - Hinweis : Geben Sie den Namen der Funktion und keinen Funktionsaufruf an; Verwenden
some_func
und nichtsome_func()
. - Das Erstellen eines Thread-Objekts startet keinen Thread; Der Aufruf der
start()
Methode für das Thread-Objekt funktioniert. - Um die Anzahl der aktiven Threads zu erhalten, verwenden wir die Funktion
active_count()
.
Das Python-Skript wird im Haupt-Thread ausgeführt, und wir erstellen einen weiteren Thread ( thread1
), um die Funktion some_func
, sodass die Anzahl der aktiven Threads zwei beträgt, wie in der Ausgabe zu sehen ist:
# Output Running some_func... 2 Finished running some_func.
Wenn wir uns die Ausgabe genauer ansehen, sehen wir, dass beim Start von thread1
die erste print-Anweisung ausgeführt wird. Aber während des Sleep-Vorgangs wechselt der Prozessor zum Haupt-Thread und gibt die Anzahl der aktiven Threads aus – ohne darauf zu warten, dass thread1
die Ausführung beendet.

Warten, bis Threads die Ausführung beenden
Wenn Sie möchten, dass thread1
die Ausführung beendet, können Sie nach dem Start des Threads die Methode join()
dafür aufrufen. Dadurch wird darauf gewartet, dass thread1
die Ausführung beendet, ohne zum Hauptthread zu wechseln.
import threading import time def some_func(): print("Running some_func...") time.sleep(2) print("Finished running some_func.") thread1 = threading.Thread(target=some_func) thread1.start() thread1.join() print(threading.active_count())
Jetzt hat thread1
die Ausführung beendet, bevor wir die Anzahl der aktiven Threads ausgeben. Es läuft also nur der Haupt-Thread, was bedeutet, dass die Anzahl der aktiven Threads eins ist.
# Output Running some_func... Finished running some_func. 1
So führen Sie mehrere Threads in Python aus
Als Nächstes erstellen wir zwei Threads, um zwei verschiedene Funktionen auszuführen.
Hier ist count_down
eine Funktion, die eine Zahl als Argument akzeptiert und von dieser Zahl bis Null herunterzählt.
def count_down(n): for i in range(n,-1,-1): print(i)
Wir definieren count_up
, eine weitere Python-Funktion, die von Null bis zu einer bestimmten Zahl zählt.
def count_up(n): for i in range(n+1): print(i)
Bei Verwendung der Funktion
range()
mit der Syntaxrange(start, stop, step)
wird der Endpunktstop
standardmäßig ausgeschlossen.– Um von einer bestimmten Zahl bis Null herunterzuzählen, können Sie einen negativen
step
von -1 verwenden und denstop
auf -1 setzen, sodass Null enthalten ist.– Um bis
n
, müssen Sie denstop
aufn + 1
setzen. Da die Standardwerte vonstart
undstep
0 bzw. 1 sind, können Sierange(n + 1)
verwenden, um die Sequenz 0 bis n zu erhalten.
Als Nächstes definieren wir zwei Threads, thread1
und thread2
, um die Funktionen count_down
bzw. count_up
. Wir fügen print
Anweisungen und sleep
-Operationen für beide Funktionen hinzu.
Beachten Sie beim Erstellen der Thread-Objekte, dass die Argumente für die Zielfunktion als Tupel angegeben werden sollten – für den args
-Parameter. Da beide Funktionen ( count_down
und count_up
) ein Argument aufnehmen. Sie müssen explizit ein Komma nach dem Wert einfügen. Dadurch wird sichergestellt, dass das Argument weiterhin als Tupel übergeben wird, da die nachfolgenden Elemente als None
abgeleitet werden.
import threading import time def count_down(n): for i in range(n,-1,-1): print("Running thread1....") print(i) time.sleep(1) def count_up(n): for i in range(n+1): print("Running thread2...") print(i) time.sleep(1) thread1 = threading.Thread(target=count_down,args=(10,)) thread2 = threading.Thread(target=count_up,args=(5,)) thread1.start() thread2.start()
In der Ausgabe:
- Die Funktion
count_up
läuft aufthread2
und zählt von 0 beginnend bis 5 hoch. - Die
count_down
Funktion läuft aufthread1
und zählt von 10 auf 0 herunter.
# Output Running thread1.... 10 Running thread2... 0 Running thread1.... 9 Running thread2... 1 Running thread1.... 8 Running thread2... 2 Running thread1.... 7 Running thread2... 3 Running thread1.... 6 Running thread2... 4 Running thread1.... 5 Running thread2... 5 Running thread1.... 4 Running thread1.... 3 Running thread1.... 2 Running thread1.... 1 Running thread1.... 0
Sie können sehen, dass thread1
und thread2
alternativ ausgeführt werden, da beide eine Warteoperation (sleep) beinhalten. Sobald die count_up
Funktion das Zählen bis 5 beendet hat, ist thread2
nicht mehr aktiv. Wir erhalten also die Ausgabe, die nur thread1
entspricht.
Zusammenfassen
In diesem Lernprogramm haben Sie gelernt, wie Sie das integrierte Threading-Modul von Python verwenden, um Multithreading zu implementieren. Hier ist eine Zusammenfassung der wichtigsten Takeaways:
- Der Thread -Konstruktor kann verwendet werden, um ein Thread-Objekt zu erstellen. Durch die Verwendung von threading.Thread(target=<callable>,args=(<tuple of args>)) wird ein Thread erstellt, der das aufrufbare Ziel mit den in args angegebenen Argumenten ausführt.
- Das Python-Programm wird auf einem Haupt-Thread ausgeführt, sodass die von Ihnen erstellten Thread-Objekte zusätzliche Threads sind. Sie können die Funktion active_count() aufrufen, die die Anzahl der aktiven Threads in jeder Instanz zurückgibt.
- Sie können einen Thread mit der start()- Methode für das Thread-Objekt starten und warten, bis die Ausführung mit der join()- Methode abgeschlossen ist.
Sie können zusätzliche Beispiele codieren, indem Sie die Wartezeiten anpassen, eine andere E/A-Operation ausprobieren und vieles mehr. Achten Sie darauf, Multithreading in Ihren kommenden Python-Projekten zu implementieren. Viel Spaß beim Codieren!