Ich habe eine Frage, die die Warteschlange im Modul multiprocessing
in Python 3
Das sagen sie in den Programmierrichtlinien :
Bedenken Sie, dass ein Prozess, der Elemente in eine Warteschlange gestellt hat, vorher wartet Beenden, bis alle gepufferten Objekte vom "Feeder" -Thread zugestellt sind das darunterliegende Rohr. (Der Child - Prozess kann den Queue.cancel_join_thread Methode der Warteschlange, um dieses Verhalten zu vermeiden.)
Dies bedeutet, dass immer wenn Sie eine Warteschlange verwenden, Sie alle sicherstellen müssen Gegenstände, die in die Warteschlange gestellt wurden, werden schließlich vor der Prozess ist verbunden. Andernfalls können Sie nicht sicher sein, dass Prozesse, die Die Elemente in der Warteschlange werden beendet. Erinnere dich auch an das Nicht-Dämonische Prozesse werden automatisch verknüpft.
Ein Deadlock-Beispiel ist das folgende:
%Vor%Ein Fix hier wäre, die letzten zwei Zeilen zu tauschen (oder einfach die p.join () Zeile).
Offensichtlich sollte queue.get()
nicht nach einem join()
aufgerufen werden.
Es gibt jedoch Beispiele für die Verwendung von Warteschlangen, in denen get
nach einem join
like:
Ich habe dieses Programm ausgeführt und es funktioniert (auch als eine Lösung für die StackOverFlow-Frage Python 3 - Multiprocessing - Queue.get () antwortet nicht ).
Könnte mir jemand helfen zu verstehen, was die Regel für den Deadlock hier ist?
Die Warteschlangenimplementierung in Multiprocessing, die den Datentransfer zwischen Prozessen ermöglicht, basiert auf Standard-OS-Pipes.
OS-Pipes sind nicht unendlich lang, so dass der Prozess, der Daten in die Warteschlange stellt, während der Operation put()
im Betriebssystem blockiert werden kann, bis ein anderer Prozess get()
verwendet, um Daten aus der Warteschlange abzurufen.
Bei kleinen Datenmengen, wie der in Ihrem Beispiel, kann der Hauptprozess join()
alle erzeugten Teilprozesse bilden und dann die Daten übernehmen. Das funktioniert oft gut, skaliert aber nicht und es ist nicht klar, wann es kaputt gehen wird.
Aber es wird sicherlich mit großen Datenmengen brechen. Der Unterprozess wird in put()
blockiert, während der Hauptprozess einige Daten mit get()
aus der Warteschlange entfernt. Der Hauptprozess wird jedoch in join()
blockiert, während er darauf wartet, dass der Unterprozess beendet wird. Dies führt zu einem Deadlock.
Hier ist ein Beispiel, in dem ein Benutzer dieses genaue Problem hatte . Ich habe dort einen Code in einer Antwort gepostet, der ihm geholfen hat, sein Problem zu lösen.
Rufen Sie join()
nicht für ein Prozessobjekt auf, bevor Sie alle Nachrichten aus der gemeinsam genutzten Warteschlange erhalten haben.
Ich habe die folgende Problemumgehung verwendet, damit Prozesse beendet werden können, bevor alle Ergebnisse verarbeitet wurden:
%Vor%Es kann verkürzt werden, aber ich habe es länger gelassen, um für Neulinge klarer zu sein.
Hier ist resultQueue
das multiprocess.Queue
, das mit multiprocess.Process
-Objekten geteilt wurde. Nach diesem Codeblock erhalten Sie das Array result
mit allen Nachrichten aus der Warteschlange.
Das Problem besteht darin, dass der Eingangspuffer der Warteschlangenleitung, der die Nachrichten empfängt, voll werden kann, was einen unendlichen Block des Schreibers (s) verursacht, bis genug Platz vorhanden ist, um die nächste Nachricht zu empfangen. Sie haben also drei Möglichkeiten, das Blockieren zu vermeiden:
multiprocessing.connection.BUFFER
Größe (nicht so gut) Tags und Links python multithreading