Beherrschung der Inter-Thread-Kommunikation in Python:Synchronisierung und Datenfreigabe
Inter-Thread-Kommunikation bezieht sich auf den Prozess der Ermöglichung der Kommunikation und Synchronisierung zwischen Threads innerhalb eines Python-Multithread-Programms.
Im Allgemeinen teilen sich Threads in Python den gleichen Speicherplatz innerhalb eines Prozesses, wodurch sie Daten austauschen und ihre Aktivitäten über gemeinsam genutzte Variablen, Objekte und spezielle Synchronisierungsmechanismen koordinieren können, die vom Threading-Modul bereitgestellt werden.
Um die Kommunikation zwischen Threads zu erleichtern, stellt das Threading-Modul verschiedene Synchronisierungsprimitive wie Sperren, Ereignisse, Bedingungen und Semaphorobjekte bereit. In diesem Tutorial erfahren Sie, wie Sie das Ereignis- und Bedingungsobjekt für die Kommunikation zwischen Threads in einem Multithread-Programm verwenden.
Das Ereignisobjekt
Ein Event-Objekt verwaltet den Status eines internen Flags, sodass Threads warten oder gesetzt werden können. Das Ereignisobjekt stellt Methoden zur Steuerung des Status dieses Flags bereit, sodass Threads ihre Aktivitäten basierend auf gemeinsamen Bedingungen synchronisieren können.
Das Flag ist zunächst „false“ und wird mit der Methode „set()“ zu „true“ und mit der Methode „clear()“ auf „false“ zurückgesetzt. Die Methode wait() blockiert, bis das Flag wahr ist.
Im Folgenden sind die wichtigsten Methoden des Event-Objekts aufgeführt −
- is_set():Gibt True genau dann zurück, wenn das interne Flag true ist.
- set():Setzt das interne Flag auf true. Alle Threads, die darauf warten, dass es wahr wird, werden geweckt. Threads, die wait() aufrufen, sobald das Flag wahr ist, werden überhaupt nicht blockiert.
- clear():Setzt das interne Flag auf false zurück. Anschließend werden Threads, die wait() aufrufen, blockiert, bis set() aufgerufen wird, um das interne Flag wieder auf true zu setzen.
- wait(timeout=None):Blockieren, bis das interne Flag wahr ist. Wenn das interne Flag bei der Eingabe wahr ist, kehren Sie sofort zurück. Andernfalls wird blockiert, bis ein anderer Thread set() aufruft, um das Flag auf „true“ zu setzen, oder bis das optionale Timeout auftritt. Wenn das Timeout-Argument vorhanden ist und nicht None, sollte es eine Gleitkommazahl sein, die ein Timeout für den Vorgang in Sekunden angibt.
Beispiel
Der folgende Code versucht, den Verkehrsfluss zu simulieren, der durch den Zustand der Ampel entweder GRÜN oder ROT gesteuert wird.
Es gibt zwei Threads im Programm, die auf zwei verschiedene Funktionen abzielen. Die Funktion signal_state() setzt und setzt regelmäßig das Ereignis zurück, das den Signalwechsel von GRÜN auf ROT anzeigt.
Die Funktion „traffic_flow()“ wartet darauf, dass das Ereignis gesetzt wird, und führt eine Schleife aus, bis es gesetzt bleibt.
from threading import Event, Thread
import time
terminate = False
def signal_state():
global terminate
while not terminate:
time.sleep(0.5)
print("Traffic Police Giving GREEN Signal")
event.set()
time.sleep(1)
print("Traffic Police Giving RED Signal")
event.clear()
def traffic_flow():
global terminate
num = 0
while num < 10 and not terminate:
print("Waiting for GREEN Signal")
event.wait()
print("GREEN Signal ... Traffic can move")
while event.is_set() and not terminate:
num += 1
print("Vehicle No:", num," Crossing the Signal")
time.sleep(1)
print("RED Signal ... Traffic has to wait")
event = Event()
t1 = Thread(target=signal_state)
t2 = Thread(target=traffic_flow)
t1.start()
t2.start()
# Terminate the threads after some time
time.sleep(5)
terminate = True
# join all threads to complete
t1.join()
t2.join()
print("Exiting Main Thread")
Ausgabe
Wenn Sie den obigen Code ausführen, erhalten Sie die folgende Ausgabe:-
Waiting for GREEN Signal Traffic Police Giving GREEN Signal GREEN Signal ... Traffic can move Vehicle No: 1 Crossing the Signal Traffic Police Giving RED Signal RED Signal ... Traffic has to wait Waiting for GREEN Signal Traffic Police Giving GREEN Signal GREEN Signal ... Traffic can move Vehicle No: 2 Crossing the Signal Vehicle No: 3 Crossing the Signal Traffic Police Giving RED Signal Traffic Police Giving GREEN Signal Vehicle No: 4 Crossing the Signal Traffic Police Giving RED Signal RED Signal ... Traffic has to wait Traffic Police Giving GREEN Signal Traffic Police Giving RED Signal Exiting Main Thread
Das Bedingungsobjekt
Das Condition-Objekt im Threading-Modul von Python bietet einen erweiterten Synchronisierungsmechanismus. Dadurch können Threads auf eine Benachrichtigung von einem anderen Thread warten, bevor sie fortfahren. Das Condition-Objekt ist immer mit einer Sperre verknüpft und stellt Mechanismen zur Signalisierung zwischen Threads bereit.
Im Folgenden finden Sie die Syntax der Klasse threading.Condition() −
threading.Condition(lock=None)
Nachfolgend sind die wichtigsten Methoden des Condition-Objekts aufgeführt −
- acquire(*args):Erwerben Sie die zugrunde liegende Sperre. Diese Methode ruft die entsprechende Methode für die zugrunde liegende Sperre auf; Der Rückgabewert ist der von der Methode zurückgegebene Wert.
- release():Gibt die zugrunde liegende Sperre frei. Diese Methode ruft die entsprechende Methode für die zugrunde liegende Sperre auf; Es gibt keinen Rückgabewert.
- wait(timeout=None):Diese Methode gibt die zugrunde liegende Sperre frei und blockiert dann, bis sie durch einen notify()- oder notify_all()-Aufruf für dieselbe Bedingungsvariable in einem anderen Thread aktiviert wird oder bis das optionale Timeout auftritt. Sobald es aktiviert wird oder die Zeit abgelaufen ist, erhält es die Sperre erneut und kehrt zurück.
- wait_for(predicate, timeout=None):Diese Dienstprogrammmethode kann wait() wiederholt aufrufen, bis das Prädikat erfüllt ist oder bis ein Timeout auftritt. Der Rückgabewert ist der letzte Rückgabewert des Prädikats und wird als „False“ ausgewertet, wenn die Methode abgelaufen ist.
- notify(n=1):Diese Methode weckt höchstens n Threads, die auf die Bedingungsvariable warten; Es ist ein No-Op, wenn keine Threads warten.
- notify_all():Weckt alle Threads auf, die auf diese Bedingung warten. Diese Methode verhält sich wie notify(), weckt jedoch alle wartenden Threads auf und nicht nur einen. Wenn der aufrufende Thread beim Aufruf dieser Methode die Sperre nicht erworben hat, wird ein RuntimeError ausgelöst.
Beispiel
Dieses Beispiel demonstriert eine einfache Form der Inter-Thread-Kommunikation mithilfe des Condition-Objekts des Python-Threading-Moduls. Hier werden Thread_a und Thread_b über ein Condition-Objekt kommuniziert, Thread_a wartet, bis er eine Benachrichtigung von Thread_b erhält. Der Thread_b schläft zwei Sekunden lang, bevor er Thread_a benachrichtigt, und wird dann beendet.
from threading import Condition, Thread
import time
c = Condition()
def thread_a():
print("Thread A started")
with c:
print("Thread A waiting for permission...")
c.wait()
print("Thread A got permission!")
print("Thread A finished")
def thread_b():
print("Thread B started")
with c:
time.sleep(2)
print("Notifying Thread A...")
c.notify()
print("Thread B finished")
Thread(target=thread_a).start()
Thread(target=thread_b).start()
Ausgabe
Wenn Sie den obigen Code ausführen, erhalten Sie die folgende Ausgabe:-
Thread A started Thread A waiting for permission... Thread B started Notifying Thread A... Thread B finished Thread A got permission! Thread A finished
Beispiel
Hier ist ein weiterer Code, der zeigt, wie das Condition-Objekt für die Kommunikation zwischen Threads verwendet wird. Dabei führt der Thread t2 die Funktion taskB() aus und der Thread t1 führt die Funktion taskA() aus. Der t1-Thread erfasst die Bedingung und benachrichtigt sie.
Zu diesem Zeitpunkt befindet sich der T2-Thread im Wartezustand. Nachdem die Bedingung aufgehoben wurde, verbraucht der wartende Thread die von der Benachrichtigungsfunktion generierte Zufallszahl.
from threading import Condition, Thread
import time
import random
numbers = []
def taskA(c):
for _ in range(5):
with c:
num = random.randint(1, 10)
print("Generated random number:", num)
numbers.append(num)
print("Notification issued")
c.notify()
time.sleep(0.3)
def taskB(c):
for i in range(5):
with c:
print("waiting for update")
while not numbers:
c.wait()
print("Obtained random number", numbers.pop())
time.sleep(0.3)
c = Condition()
t1 = Thread(target=taskB, args=(c,))
t2 = Thread(target=taskA, args=(c,))
t1.start()
t2.start()
t1.join()
t2.join()
print("Done")
Wenn Sie diesen Code ausführen, wird die folgende Ausgabe erzeugt:-
waiting for update Generated random number: 2 Notification issued Obtained random number 2 Generated random number: 5 Notification issued waiting for update Obtained random number 5 Generated random number: 1 Notification issued waiting for update Obtained random number 1 Generated random number: 9 Notification issued waiting for update Obtained random number 9 Generated random number: 2 Notification issued waiting for update Obtained random number 2 Done
Python
- PIP unter Windows installieren:Eine vollständige Schritt-für-Schritt-Anleitung
- Modul in Python mit Beispielen importieren
- Verwenden Sie den Unterstrich in The REPL
- Meistern Sie das Ausführen von Python-Skripten:Eine umfassende Schritt-für-Schritt-Anleitung
- Python TUPLE – Packen, Entpacken, Vergleichen, Slicing, Löschen, Key
- Fragen und Antworten zum Master-Python-Interview – Ihr ultimativer Vorbereitungsleitfaden
- Python-Paket
- Python-Debugger:Verbessern Sie mühelos Ihre Debug-Fähigkeiten
- Facebook-Login mit Python:FB-Login-Beispiel
- Datei kopieren in Python:Methode shutdown.copy(), shutdown.copystat()