Erzwingen Sie nicht das Beenden von Python-Threads
Vorwort:
Versuchen Sie nicht, einen Python-Thread mit Gewalt zu beenden. Dies ist im Hinblick auf das Service-Design unvernünftig. Multithreading wird für die kollaborative Parallelität von Aufgaben verwendet. Wenn Sie Threads gewaltsam beenden, besteht eine hohe Wahrscheinlichkeit, dass unerwartete Fehler auftreten. Bitte beachten Sie, dass die Sperrressource nicht freigegeben wird, da der Thread beendet wird!
Wir können zwei gängige Beispiele nennen:
1. Thread A hat die Sperre erhalten, weil er gewaltsam beendet wurde und die Sperrressource nicht rechtzeitig mit release() freigegeben wurde. Dann werden alle Threads die Sperre erhalten beim Erwerb von Ressourcen blockiert, was ein typisches Deadlock-Szenario darstellt.
2. In einem üblichen Produktions-Konsumenten-Szenario ruft der Konsument Aufgaben aus der Aufgabenwarteschlange ab, wirft die laufende Aufgabe jedoch nicht zurück in die Warteschlange, nachdem sie beendet wurde, was zu Datenverlust führt.
Es gibt folgende Möglichkeiten, Threads in Java und Python zu beenden:
Java verfügt über drei Methoden, um Threads zu beenden:
1 Exit-Flag, um den Thread normal zu beenden, d. h. der Thread wird beendet, wenn die Ausführungsmethode abgeschlossen ist.
2. Verwenden Sie die Stop-Methode, um den Thread zwangsweise zu beenden (nicht empfohlen, da Stop dasselbe ist wie Anhalten und Fortsetzen und unvorhersehbare Ergebnisse auftreten können).
3. Verwenden Sie die Interrupt-Methode, um den Thread zu unterbrechen.
Python kann zwei Methoden haben:
1. Exit-Markierung
2. Verwenden Sie ctypes, um den Thread gewaltsam zu beenden
Nein Angelegenheit In einer Python- oder Java-Umgebung besteht die ideale Möglichkeit, einen Thread zu stoppen und zu beenden, darin, den Thread Selbstmord begehen zu lassen. Der sogenannte Thread-Selbstmord bedeutet, dass Sie ihm ein Flag geben und er den Thread verlässt.
Im Folgenden werden wir verschiedene Methoden verwenden, um die abnormale Situation beim Stoppen des Python-Threads zu testen. Wir betrachten alle Ausführungsthreads eines Prozesses. Der Prozess verwendet Steuerressourcen und der Thread wird als Planungseinheit verwendet. Um für die Ausführung geplant zu werden, muss ein Thread vorhanden sein der Prozess.
ps -mp 31449 -o THREAD,tid USER %CPU PRI SCNT WCHAN USER SYSTEM TID root 0.0 - - - - - - root 0.0 19 - poll_s - - 31449 root 0.0 19 - poll_s - - 31450
Nachdem wir alle Threads des Prozesses erhalten haben, wissen wir durch Strace, dass 31450 die Thread-ID ist, die getötet werden muss. Es erscheint eine Situation, in der der gesamte Prozess abstürzt. In einer Multithread-Umgebung wird das generierte Signal an den gesamten Prozess weitergeleitet. Im Allgemeinen haben alle Threads die Möglichkeit, dieses Signal zu empfangen. Der Prozess führt die Signalverarbeitungsfunktion in dem Thread-Kontext aus, der das Signal empfängt es. Schwer zu wissen. Mit anderen Worten: Das Signal wird zufällig an einen Thread des Prozesses gesendet.
strace -p <span style="font-size:14px;line-height:21px;">31450</span> Process <span style="font-size:14px;line-height:21px;">31450</span> attached - interrupt to quit select(0, NULL, NULL, NULL, {0, 320326}) = 0 (Timeout) select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout) select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout) select(0, NULL, NULL, NULL, {1, 0}) = ? ERESTARTNOHAND (To be restarted) --- SIGTERM (Terminated) @ 0 (0) --- Process <span style="font-size:14px;line-height:21px;">31450</span> detached
Das obige Problem stimmt tatsächlich mit der Beschreibung von pthread überein. Wenn wir die Signalverarbeitungsfunktion zum Python-Code hinzufügen, kann die Rückruffunktion verhindern, dass der gesamte Prozess beendet wird. Mit anderen Worten: Die Signalfunktion kann nicht genau identifizieren bestimmter Thread. Obwohl Sie das Signal an die Thread-ID 31450 senden, ist der Signalakzeptor einer der Prozesse, zu denen es gehört. Darüber hinaus sind die an die Signalverarbeitungsfunktion übergebenen Parameter nur die Signalnummer und der Signalstapel, die optional sind.
Nach dem Hinzufügen der Signalverarbeitung wird der Prozess nicht beendet
select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout) select(0, NULL, NULL, NULL, {1, 0}) = ? ERESTARTNOHAND (To be restarted) --- SIGTERM (Terminated) @ 0 (0) --- rt_sigreturn(0xffffffff) = -1 EINTR (Interrupted system call) select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout) select(0, NULL, NULL, NULL, {1, 0}) = 0 (Timeout)
Wenn Sie einen Thread von extern beenden möchten Benachrichtigung , dann können Sie RPC-Dienste erstellen und verwenden oder auf andere Weise kommunizieren, Signalsignale jedoch nicht, da sie keine weiteren Informationen übertragen können.
Python-Threads werden nicht simuliert, es handelt sich um echte Kernel-Threads. Der Kernel ruft die pthread-Methode auf, aber die obere Schicht von Python bietet keine Methode zum Schließen des Threads, daher müssen wir sie selbst verstehen. Es wird dringend empfohlen, Ereignis- oder benutzerdefinierte Flag-Bit-Methoden zu verwenden. Wenn Sie den Thread zwangsweise beenden müssen, können Sie das Beenden mit der Python-ctypes-Methode „PyThreadState SetAsyncExc“ erzwingen, was keine Auswirkungen auf den laufenden Python-Dienst hat.
Das Implementierungsprinzip dieser Funktion ist relativ einfach. Tatsächlich besteht es darin, ein Flag in der virtuellen Python-Maschine zu setzen, und dann führt die virtuelle Maschine eine Ausnahme aus, um den Thread abzubrechen Die Maschine hilft Ihnen beim Erstellen eines Test-Cache. Denken Sie daran, einen Thread in Python nicht extern zu beenden. Obwohl Sie die Thread-ID über ctypes finden können, wird durch das direkte Beenden der gesamte Prozess beendet.
Der folgende Code ist ein Beispiel für die Verwendung von ctypes zum Beenden eines Threads. Er wird nicht empfohlen, da er zu unhöflich ist.
import ctypes def terminate_thread(thread): if not thread.isAlive(): return exc = ctypes.py_object(SystemExit) res = ctypes.pythonapi.PyThreadState_SetAsyncExc( ctypes.c_long(thread.ident), exc) if res == 0: raise ValueError("nonexistent thread id") elif res > 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None) raise SystemError("PyThreadState_SetAsyncExc failed")
Werfen wir einen kurzen Blick auf den PyThreadState-Quellcode. Kurz gesagt, der Ausnahmemodus des Threads wird ausgelöst. Interessierte können das Design von Python pystate.c lesen und mit einigen Videos auf YouTube teilen.
int PyThreadState_SetAsyncExc(long id, PyObject *exc) { PyInterpreterState *interp = GET_INTERP_STATE(); ... HEAD_LOCK(); for (p = interp->tstate_head; p != NULL; p = p->next) { if (p->thread_id == id) { 从链表里找到线程的id,避免死锁,我们需要释放head_mutex。 PyObject *old_exc = p->async_exc; Py_XINCREF(exc); #增加该对象的引用数 p->async_exc = exc; # 更为exc模式 HEAD_UNLOCK(); Py_XDECREF(old_exc); # 因为要取消,当然也就递减引用 ... return 1; #销毁线程成功 } } HEAD_UNLOCK(); return 0; }
Nativer Posix-Pthread kann ptread_cancel(tid) verwenden, um den untergeordneten Thread im Hauptthread zu beenden. Die Thread-Bibliothek von Python unterstützt dies jedoch nicht. Der Grund dafür ist, dass wir einen Thread nicht gewaltsam beenden sollten. Dies birgt viele versteckte Gefahren und der Thread sollte sich selbst beenden dürfen. Daher besteht in Python die empfohlene Methode darin, einen Sub-Thread zu durchlaufen, um ein Flag zu ermitteln, das Flag im Haupt-Thread zu ändern und sich selbst zu beenden, wenn der Sub-Thread die Flag-Änderung liest.
Ähnlich dieser Logik:
def consumer_threading(): t1_stop= threading.Event() t1 = threading.Thread(target=thread1, args=(1, t1_stop)) t2_stop = threading.Event() t2 = threading.Thread(target=thread2, args=(2, t2_stop)) time.sleep(duration) #stop the thread2 t2_stop.set() def thread1(arg1, stop_event): while(not stop_event.is_set()): #similar to time.sleep() stop_event.wait(time) pass def thread2(arg1, stop_event): while(not stop_event.is_set()): stop_event.wait(time) pass
Eine kurze Zusammenfassung: Obwohl wir Pystats in Ctypes verwenden können, um Threads zu steuern, ist diese Methode der groben Unterbrechung von Threads unvernünftig. Bitte verwenden Sie den Selbstmordmodus! Was passiert, wenn Ihr Thread io blockiert und das Ereignis nicht ermitteln kann? Ihr Programm muss mindestens über ein aktives Timeout auf der Netzwerk-E/A-Ebene verfügen, um eine kontinuierliche Blockierung zu vermeiden.
Weitere verwandte Artikel zum Thema, keine erzwungenen Methoden zum Beenden von Python-Threads zu verwenden, finden Sie auf der chinesischen PHP-Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Lösung für Erlaubnisprobleme beim Betrachten der Python -Version in Linux Terminal Wenn Sie versuchen, die Python -Version in Linux Terminal anzuzeigen, geben Sie Python ein ...

Wie lehre ich innerhalb von 10 Stunden die Grundlagen für Computer -Anfänger für Programmierungen? Wenn Sie nur 10 Stunden Zeit haben, um Computer -Anfänger zu unterrichten, was Sie mit Programmierkenntnissen unterrichten möchten, was würden Sie dann beibringen ...

Bei der Verwendung von Pythons Pandas -Bibliothek ist das Kopieren von ganzen Spalten zwischen zwei Datenrahmen mit unterschiedlichen Strukturen ein häufiges Problem. Angenommen, wir haben zwei Daten ...

Wie kann man nicht erkannt werden, wenn Sie Fiddlereverywhere für Man-in-the-Middle-Lesungen verwenden, wenn Sie FiddLereverywhere verwenden ...

Regelmäßige Ausdrücke sind leistungsstarke Tools für Musteranpassung und Textmanipulation in der Programmierung, wodurch die Effizienz bei der Textverarbeitung in verschiedenen Anwendungen verbessert wird.

Wie hört Uvicorn kontinuierlich auf HTTP -Anfragen an? Uvicorn ist ein leichter Webserver, der auf ASGI basiert. Eine seiner Kernfunktionen ist es, auf HTTP -Anfragen zu hören und weiterzumachen ...

Wie erstellt in Python ein Objekt dynamisch über eine Zeichenfolge und ruft seine Methoden auf? Dies ist eine häufige Programmieranforderung, insbesondere wenn sie konfiguriert oder ausgeführt werden muss ...

In dem Artikel werden beliebte Python-Bibliotheken wie Numpy, Pandas, Matplotlib, Scikit-Learn, TensorFlow, Django, Flask und Anfragen erörtert, die ihre Verwendung in wissenschaftlichen Computing, Datenanalyse, Visualisierung, maschinellem Lernen, Webentwicklung und h beschreiben
