Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> Python

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 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:

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:

  1. Der Faden Modul und
  2. 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

  1. Diese Anweisungen importieren die Zeit- und Thread-Module, die verwendet werden, um die Ausführung und Verzögerung der Python-Threads zu handhaben.
  2. 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.
  3. 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:

  1. definiere eine Klasse, die die Thread-Klasse erweitert
  2. Überschreiben Sie die __init__ Konstruktor
  3. Ü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

  1. 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.
  2. 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.
  3. 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). ).
  4. 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.
  5. 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.
  6. 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.

Ein Philosoph muss zu jeder Zeit entweder essen oder denken.

Außerdem muss ein Philosoph die zwei Gabeln neben sich nehmen (d. h. die linke und die rechte Gabel), bevor er die Spaghetti essen kann. Das Problem des Deadlocks tritt auf, wenn alle fünf Philosophen gleichzeitig ihre rechte Gabel in die Hand nehmen.

Da jeder der Philosophen eine Gabel hat, werden sie alle warten, bis die anderen ihre Gabel weglegen. Folglich wird keiner von ihnen Spaghetti essen können.

In ähnlicher Weise tritt in einem nebenläufigen System ein Deadlock auf, wenn verschiedene Threads oder Prozesse (Philosophen) gleichzeitig versuchen, die gemeinsam genutzten Systemressourcen (Forks) zu erwerben. Infolgedessen hat keiner der Prozesse die Möglichkeit, ausgeführt zu werden, da sie auf eine andere Ressource warten, die von einem anderen Prozess gehalten wird.

Rennbedingungen

Eine Wettlaufbedingung 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 variable
for x in range(100):
    print(i)
    i+=1;

Wenn Sie n erstellen Anzahl der Threads, die diesen Code gleichzeitig ausführen, können Sie den Wert von i (der von den Threads geteilt wird) nicht bestimmen, wenn das Programm die Ausführung beendet. Dies liegt daran, dass sich in einer echten Multithreading-Umgebung die Threads überlappen können und der Wert von i, der von einem Thread abgerufen und modifiziert wurde, sich 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 lösen können.

Synchronisieren von Threads

Um Racebedingungen, Deadlocks und andere Thread-basierte Probleme zu bewältigen, stellt das Threading-Modul die Sperre bereit Objekt. Die Idee ist, dass ein Thread, wenn er auf eine bestimmte Ressource zugreifen möchte, eine Sperre für diese Ressource erwirbt. Sobald ein Thread eine bestimmte Ressource sperrt, kann kein anderer Thread darauf zugreifen, bis die Sperre aufgehoben wird. Als Ergebnis werden die Änderungen an der Ressource atomar sein und Race Conditions werden abgewendet.

Eine Sperre ist ein einfaches Synchronisationselement, das vom __thread implementiert wird Modul. Eine Sperre kann sich jederzeit in einem von zwei Zuständen befinden:gesperrt oder entsperrt. Es unterstützt zwei Methoden:

  1. erwerben() Wenn der Sperrstatus entsperrt ist, wird der Aufruf der Methode „acquire()“ den Status in „gesperrt“ ändern und zurückkehren. Wenn der Zustand jedoch gesperrt ist, wird der Aufruf von „acquire()“ blockiert, bis die Methode „release()“ von einem anderen Thread aufgerufen wird.
  2. loslassen() Die Methode release() wird verwendet, um den Zustand auf entsperrt zu setzen, d. h. um eine Sperre freizugeben. Es kann von jedem Thread aufgerufen werden, nicht unbedingt von dem, der die Sperre erworben hat.

Hier ist ein Beispiel für die Verwendung von Sperren in Ihren Apps. Starten Sie Ihren 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 jetzt F5. Sie sollten eine Ausgabe wie diese sehen:

CODE-ERKLÄRUNG

  1. Hier erstellen Sie einfach eine neue Sperre, indem Sie threading.Lock() aufrufen Fabrikfunktion. Intern gibt Lock() eine Instanz der effektivsten konkreten Lock-Klasse zurück, die von der Plattform verwaltet wird.
  2. In der ersten Anweisung erwerben Sie die Sperre, indem Sie die Methode „acquire()“ aufrufen. Wenn die Sperre erteilt wurde, drucken Sie „Sperre erworben“ aus zur Konsole. Sobald der gesamte Code, den der Thread ausführen soll, ausgeführt wurde, geben Sie die Sperre frei, indem Sie die Methode release() aufrufen.

Die Theorie ist gut, aber woher wissen Sie, dass das Schloss wirklich funktioniert hat? Wenn Sie sich die Ausgabe ansehen, sehen Sie, dass jede der Druckanweisungen genau eine Zeile auf einmal druckt. Erinnern Sie sich daran, dass in einem früheren Beispiel die Ausgaben von print willkürlich waren, weil mehrere Threads gleichzeitig auf die Methode print() zugegriffen haben. Hier wird die Druckfunktion erst aufgerufen, nachdem die Sperre erworben wurde. Die Ausgaben 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:

  1. RLocks
  2. Semaphoren
  3. Bedingungen
  4. Ereignisse und
  5. Barrieren

Globale Interpreter-Sperre (und wie man damit umgeht)

Bevor wir uns mit den Details der GIL von Python befassen, wollen wir einige Begriffe definieren, die für das Verständnis des folgenden Abschnitts nützlich sein werden:

  1. CPU-gebundener Code:Dies bezieht sich auf jeden Code, der direkt von der CPU ausgeführt wird.
  2. E/A-gebundener Code:Dies kann jeder Code sein, der über das Betriebssystem auf das Dateisystem zugreift
  3. CPython:Es ist die Referenzimplementierung von Python und kann als der in C und Python (Programmiersprache) geschriebene Interpreter beschrieben werden.

Was ist GIL in Python?

Globale Dolmetschersperre (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 auch 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.

Eine Sperre kann verwendet werden, um sicherzustellen, dass zu einem bestimmten Zeitpunkt nur ein Thread Zugriff auf eine bestimmte Ressource hat.

Eines der Merkmale von Python ist, dass es eine globale Sperre für jeden Interpreter-Prozess verwendet, 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 E/A-Operationen auszuführen. Wenn Sie dieses Programm ausführen, passiert Folgendes:

  1. Der Python-Interpreter erstellt einen neuen Prozess und erzeugt die Threads
  2. Wenn Thread-1 zu laufen beginnt, ruft er zuerst die GIL ab und sperrt sie.
  3. Wenn Thread-2 jetzt ausgeführt werden möchte, muss er auf die Freigabe der GIL warten, selbst wenn ein anderer Prozessor frei ist.
  4. Nehmen Sie nun an, Thread-1 wartet auf eine E/A-Operation. Zu diesem Zeitpunkt wird es die GIL freigeben und Thread-2 wird sie erwerben.
  5. Nach Abschluss der E/A-Operationen muss Thread-1, wenn er jetzt ausgeführt werden möchte, 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 er Time Slicing (siehe erster Abschnitt dieses Tutorials) verwenden würde, um die Threads zu verarbeiten. Im Fall von Mehrkernprozessoren hat jedoch eine CPU-gebundene Funktion, die auf mehreren Threads ausgeführt wird, einen erheblichen Einfluss auf die Effizienz des Programms, da nicht alle verfügbaren Kerne gleichzeitig verwendet werden.

Warum wurde GIL benötigt?

Der CPython-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 es einem neuen Variablennamen zugewiesen oder einem Container hinzugefügt wird (wie Tupel, Listen usw.). Ebenso wird der Verweiszähler verringert, wenn der Verweis den Gültigkeitsbereich verlässt oder wenn die del-Anweisung aufgerufen wird. Wenn der Referenzzähler eines Objekts 0 erreicht, wird es bereinigt und der zugewiesene Speicher wird freigegeben.

Das Problem besteht jedoch darin, dass die Referenzzählvariable wie jede andere globale Variable anfällig für Wettlaufbedingungen ist. Um dieses Problem zu lösen, haben sich die Entwickler von Python entschieden, die globale Interpreter-Sperre zu verwenden. Die andere Option bestand darin, jedem Objekt eine Sperre hinzuzufügen, was zu Deadlocks und erhöhtem Overhead durch die Aufrufe von „accept()“ 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 (was sie effektiv zu Single-Thread macht). Wenn Sie mehrere CPU-Kerne in Ihrer Anwendung nutzen möchten, verwenden Sie das Multiprocessing Modul statt.

Zusammenfassung

  • Python unterstützt 2 Module für Multithreading:
    1. __Thread Modul:Es bietet eine Low-Level-Implementierung für Threading und ist veraltet.
    2. 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:
    1. Erstellen Sie eine Klasse, die den Thread erweitert Klasse.
    2. Den Konstruktor überschreiben (__init__).
    3. Den run() überschreiben Methode.
    4. Erzeuge ein Objekt dieser Klasse.
  • Ein Thread kann durch Aufrufen von start() ausgeführt werden Methode.
  • Der join() Methode kann verwendet werden, um andere Threads zu blockieren, bis dieser Thread (derjenige, auf dem join aufgerufen wurde) die Ausführung beendet.
  • Eine Racebedingung tritt auf, wenn mehrere Threads gleichzeitig auf eine gemeinsam genutzte Ressource zugreifen oder diese ändern.
  • Es kann vermieden werden, indem Threads synchronisiert werden.
  • Python unterstützt 6 Möglichkeiten zum Synchronisieren von Threads:
    1. Schlösser
    2. RLocks
    3. Semaphoren
    4. Bedingungen
    5. Ereignisse und
    6. Barrieren
  • Sperren erlauben nur einem bestimmten Thread, der die Sperre erworben hat, in den kritischen Abschnitt einzutreten.
  • Eine Sperre hat zwei primäre Methoden:
    1. erwerben() :Es setzt den Sperrzustand auf gesperrt. Wenn es für ein gesperrtes Objekt aufgerufen wird, blockiert es, bis die Ressource frei ist.
    2. loslassen() :Der Sperrstatus wird auf entsperrt gesetzt und kehrt zurück. Wenn es für ein entsperrtes Objekt aufgerufen wird, gibt es false zurück.
  • Die globale Interpreter-Sperre ist ein Mechanismus, durch den nur 1 CPython-Interpreter-Prozess gleichzeitig ausgeführt werden kann.
  • Es wurde verwendet, um die Referenzzählfunktion des Garbage Collectors von CPythons zu vereinfachen.
  • Um Python-Apps mit stark CPU-lastigen Operationen zu erstellen, sollten Sie das Multiprocessing-Modul verwenden.

Python

  1. free()-Funktion in der C-Bibliothek:Wie verwenden? Lernen Sie mit Beispiel
  2. Python String strip() Funktion mit BEISPIEL
  3. Python String count() mit BEISPIELE
  4. Python-Funktion round() mit BEISPIELE
  5. Python map() Funktion mit BEISPIELE
  6. Python Timeit() mit Beispielen
  7. Python-Zähler in Sammlungen mit Beispiel
  8. Python List count() mit BEISPIELE
  9. Python List index() mit Beispiel
  10. C# – Multithreading