Über eine Globale variable mit einem thread
Wie kann ich eine Globale variable mit thread?
Mein Python-code-Beispiel:
from threading import Thread
import time
a = 0 #global variable
def thread1(threadname):
#read variable "a" modify by thread 2
def thread2(threadname):
while 1:
a += 1
time.sleep(1)
thread1 = Thread( target=thread1, args=("Thread-1", ) )
thread2 = Thread( target=thread2, args=("Thread-2", ) )
thread1.join()
thread2.join()
Ich weiß nicht, wie man die beiden threads teilen sich eine variable.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Brauchen Sie nur zu erklären
a
als global inthread2
, so dass Sie nicht mit dem ändern einera
lokalen Funktion.In
thread1
Sie brauchen nicht etwas besonderes zu tun, solange Sie nicht versuchen, ändern Sie den Wert desa
(das würde die lokale variable erstellen, die Schatten, die Globale, die Nutzungglobal a
wenn Sie benötigen)>In einer Funktion:
wird vom compiler interpretiert werden als
assign to a => Create local variable a
, das ist nicht, was Sie wollen. Es wird wahrscheinlich fehl mit einea not initialized
Fehler, da die (lokalen) a hat in der Tat nicht initialisiert wurde:Könnten Sie bekommen, was Sie wollen, mit dem (sehr verpönt, und aus guten Gründen)
global
Schlüsselwort, etwa so:Im Allgemeinen sollten Sie jedoch vermeiden Verwendung von globalen Variablen, die werden extrem schnell von der hand. Und dies gilt insbesondere für Multithread-Programme, wo Sie keine Synchronisations-Mechanismus für Ihre
thread1
zu wissen, Wanna
geändert wurde. Kurzum: threads sind kompliziert, und Sie können nicht erwarten, haben ein intuitives Verständnis der Reihenfolge, in der die Ereignisse passiert sind, wenn zwei (oder mehr) threads, die Arbeit auf den gleichen Wert. Die Sprache, compiler, Betriebssystem, Prozessor... können ALLE spielen eine Rolle und entscheiden zum ändern der Reihenfolge der Operationen für Geschwindigkeit, Funktionalität oder anderen Gründen.Den richtigen Weg für diese Art der Sache ist die Verwendung von Python-sharing-tools (sperren
und Freunde), oder besser, zu kommunizieren, Daten über ein Warteschlange statt Sie zu teilen, z.B. wie folgt:
a
. Es ist das Standard blocking-Verhalten der Warteschlange schafft, dass die Synchronisation. Die Aussagea = q.get()
wird blockiert (warten), bis ein Wert vorhanden ist. Die variableq
ist lokal : wenn Sie einen anderen Wert zuweisen will, es wird passieren, nur lokal. Aber die Warteschlange zugeordnet, in dem code ist der, der definiert ist in der Haupt-thread.Eine Sperre sollte betrachtet werden, um zu verwenden, wie
threading.Lock
. Sehen lock-Objekte für mehr info.Die akzeptierten Antworten drucken KÖNNEN 10 von thread1, das ist nicht, was Sie wollen. Führen Sie den folgenden code zu verstehen, den Fehler leichter.
Durch ein lock verbieten kann, ändern von
a
beim Lesen mehr als einmal:Wenn der thread die variable für die lange Zeit, die Bewältigung zu einer lokalen variable zunächst ist eine gute Wahl.
Vielen Dank Jason Pan für die Annahme, dass die Methode. Die thread1 if-Anweisung ist nicht atomar, so dass, während diese Anweisung ausgeführt wird, ist es möglich, dass Thread2 verzahnt zu stören auf thread1, dass nicht-erreichbaren code zu erreichen. Ich habe organisiert, die Ideen aus der vorherigen Beiträge in ein vollständiges Demo-Programm (unten), lief ich mit Python 2.7.
Mit einigen nachdenklich Analyse ich bin mir sicher, dass wir gewinnen konnten weitere Einblicke, aber für jetzt ich denke, es ist wichtig, um zu zeigen, was passiert, wenn nicht-Atomare Verhalten erfüllt threading.
Wie vorhergesagt, in Sie das Beispiel ausführen, die "nicht erreichbar" - code manchmal auch tatsächlich zu erreichen, produzieren Ausgabe.
Nur um, wenn ich eingefügt, der eine Sperre erwerben/release-pair-Mädchen in thread1 fand ich, dass die Wahrscheinlichkeit, dass die "nicht erreichbar" Nachricht drucken wurde stark reduziert. Um zu sehen, die Nachricht, die ich reduziert die einschlafzeit um 0,01 Sek. und erhöht NN 1000.
Mit einem lock acquire/release-pair-Mädchen in thread1 ich hatte nicht erwartet, um zu sehen, die Nachricht an alle, aber es ist da. Nachdem ich eingefügt, der eine Sperre erwerben/release-paar auch in Thread2 verzahnt, wird die Nachricht nicht mehr erschienen. Im hinteren signt die Inkrement-Anweisung, die in Thread2 verzahnt wohl auch nicht atomar.
Gut, laufen Beispiel:
WARNUNG! DIES NIE TUN ZU HAUSE/ARBEIT! Nur im Klassenzimmer 😉
Verwenden Sie Semaphoren, shared-Variablen, etc. um zu vermeiden, rush Bedingungen.
und die Ausgabe:
Wenn das timing stimmt, die
a += 100
Betrieb übersprungen wird:Prozessor führt bei T
a+100
und bekommt 104. Aber es hält, und springt zum nächsten threadHier, In T+1 führt
a+1
mit altem Wert von a,a == 4
. So berechnet er 5.Sprung zurück (bei T+2), Faden 1, und schreiben
a=104
im Speicher.Nun aber zurück zu thread 2 Zeit T+3 und schreiben
a=5
im Speicher.Voila! Die nächste print-Anweisung print 5 statt 104.
SEHR fiesen Fehler reproduziert werden kann und gefangen.