Ich verwende das Twisted-Framework und erhalte RPCs asynchron. Ich habe eine andere Funktion, die alle 2 Sekunden eine Aufgabe erledigt und dazwischen schläft. Dies wird durch reactor.callInThread aufgerufen. Diese hängen von einer gemeinsamen Ressource ab, daher brauche ich eine thread-sichere Möglichkeit, auf sie zuzugreifen. Wie benutzt man kritische Abschnitte/Mutexe/Locks in Twisted?Mutex in Python Twisted
Antwort
Obwohl Sie Threads in twisted verwenden können, ist die übliche Idiom mit twisted RPC asynchron mit einem einzigen Thread zu tun. Das ist einer seiner Vorteile. Das verdrehte Framework führt den Reaktor aus und ruft Ihre Handler-Ereignisse auf, wenn RPC-Ergebnisse für Sie bereitstehen. Dann wird Ihr Code ausgeführt, und wenn Ihr Handler beendet wird, kehrt die Steuerung zum Reaktor zurück, der den nächsten Handler aufrufen wird, der Code bereithält. Auch wenn viele Dinge parallel laufen, stellt Twist sicher, dass nur eine Ihrer Funktionen gleichzeitig ausgeführt wird. Sie sollten also kein Mutexing benötigen, sondern lediglich Statusvariablen beibehalten, damit Ihre Callbacks den aktuellen Kontext kennen in Betrieb ist genug.
Wenn Sie explizit Threads erstellen und sie mit dem verdrehten Framework verwenden, benötigen Sie wahrscheinlich so etwas wie Standard Python Mutex, obwohl Sie sehr vorsichtig sein müssen, Ihren Reactor-Callback-Thread nie auf einen Mutex warten zu lassen beliebig lange als Rückrufe innerhalb des Reaktors nicht blockieren sollen.
Mit Twisted können Sie ereignisgesteuerten Code in einem einzigen Thread schreiben. Mehrere Ereignisse können in sichere Python-Nicht-Thread-sichere Datenstrukturen in einer sicheren Angelegenheit schreiben, und nicht Thread-sichere Datenstrukturen können als Mutexe verwendet werden. Wenn Sie tun beginnen, Threads zu verwenden, dann müssen Sie sich um diese Dinge kümmern. Aber Sie müssen sie nicht benutzen.
Also, wie gesagt: Verwenden Sie task.LoopingCall oder reactor.CallLater für Ihre Aufgabe. Rufen Sie niemals time.sleep() auf, lassen Sie den Reaktor zur richtigen Zeit Ihre Aufgabe nennen (und erledigen Sie andere Arbeiten zwischendurch). Reagieren Sie auf Ihre RPCs, wenn sie kommen.
Es wird nicht zwei Threads geben, die Ihren Code gleichzeitig ausführen. Sie wissen jedoch nicht, in welcher Reihenfolge Ihre Rückrufe aufgerufen werden. Sobald Sie die Kontrolle auf einen Deferred-Wert übertragen haben, hat sich der Anwendungsstatus möglicherweise bis zu dem Zeitpunkt geändert, an dem Sie ihn zurückbekommen.
hmm ok. Nun, um genau zu sein, habe ich einen Funktionsaufruf als Ergebnis von "reactor.callInThread". Diese Funktion macht alle 2 Sekunden etwas. Wie geht der Reaktor damit um? Ich möchte sicherstellen, dass der RPC nicht gleichzeitig ausgeführt wird, dass diese Funktion etwas tut. –
hah - ist die Antwort, um eine Aufgabe zu verwenden.LoopingCall stattdessen? –
Wenn Sie den Multithread-Ansatz nicht aus Gründen der Performance (CPU-Skalierung usw.) verwenden und die Funktion im anderen Thread nicht zu lange ohne Beenden ausgeführt wird (was den Reaktor-Thread blockiert), scheint dies der Fall zu sein akzeptabel. Ehrlich gesagt, wenn Sie den Threading-Ansatz benötigen, bin ich nicht sicher, was der richtige Weg ist, das Mutexing zu tun, da der Reaktor-Thread nicht blockieren darf. – bdk