2017-09-25 49 views
1

Dies ist ein Code zum Testen Threading:Python: Ausführungsreihenfolge in Threading

import threading 
import time 


episode = 0 
lock = threading.Lock() 

class Agent(threading.Thread): 
    def __init__(self, id): 
     threading.Thread.__init__(self) 
     self.id = id 

    def run(self): 
     global episode 
     while episode < 5: 
      with lock: 
       print(
        "{} : episode will be changed {} -> {}".format(
         self.id, 
         episode, 
         episode+1 
        ) 
       ) 
       episode += 1 
       print("{} : changed value -> {}".format(self.id, episode)) 
       time.sleep(1) 


if __name__ == "__main__": 
    agents = [] 
    for i in range(3): 
     agents.append(Agent(i)) 

    for agent in agents: 
     agent.start() 

Ergebnis:

0 : episode will be changed 0 -> 1 
0 : changed value -> 1 
0 : episode will be changed 1 -> 2 
0 : changed value -> 2 
0 : episode will be changed 2 -> 3 
0 : changed value -> 3 
0 : episode will be changed 3 -> 4 
0 : changed value -> 4 
0 : episode will be changed 4 -> 5 
0 : changed value -> 5 
1 : episode will be changed 5 -> 6 
1 : changed value -> 6 
2 : episode will be changed 6 -> 7 
2 : changed value -> 7 

Dies ist eines der Ergebnisse, die ich erwartet hatte:

0 : episode will be changed 0 -> 1 
0 : changed value -> 1 
2 : episode will be changed 1 -> 2 
2 : changed value -> 2 
1 : episode will be changed 2 -> 3 
1 : changed value -> 3 
2 : episode will be changed 3 -> 4 
2 : changed value -> 4 
0 : episode will be changed 4 -> 5 
0 : changed value -> 5 
    . 
    . 

Ich kann nicht verstehen, warum Thread-ID = 0 fortlaufend an erster Stelle erscheinen ... Wie ich weiß, die Ausführungsreihenfolge von Thre Werbung ist zufällig, oder?

Was ist falsch in meinem Code?

Antwort

1

Thread 0 startet zuerst, greift das Schloss und schläft , während das Schloss hält. Es gibt eine sehr kurze Zeitspanne zwischen dem Schliessen des Schlummers, dem Lock, das durch das Verlassen des Blocks with ausgelöst wird, und der Schleife, die das Schloss wieder erwirbt, so dass die Chancen ausgezeichnet sind, dass Thread 0 das Schloss wieder bekommt ... und wieder und wieder, bis episode < 5 ist endlich falsch.

eine Einrückungsebene entfernen auf Ihrem time.sleep(1) so führt sie als Teil der Schleife statt als Teil des with Block. Dann Thread 0 wird die Sperre freigeben vor seinen Schlaf beginnen, und andere Threads sind fast sicher, die Sperre zu erhalten, während Thread 0 schläft (sie haben eine ganze Sekunde, um dies zu tun, anstatt viel weniger als ein Eyeblink).

1

Sie haben nur Pech? Ich habe Ihren Code ohne etwas zu ändern getestet und bekam die folgende Ausgabe:

0 : episode will be changed 0 -> 1 
0 : changed value -> 1 
1 : episode will be changed 1 -> 2 
1 : changed value -> 2 
2 : episode will be changed 2 -> 3 
2 : changed value -> 3 
2 : episode will be changed 3 -> 4 
2 : changed value -> 4 
2 : episode will be changed 4 -> 5 
2 : changed value -> 5 
0 : episode will be changed 5 -> 6 
0 : changed value -> 6 
1 : episode will be changed 6 -> 7 
1 : changed value -> 7 
+0

Ich glaube nicht, das eine Antwort sein sollte – Unni

+0

@Unni Also, was tun Sie erwarten? – Sraw

+0

Ich denke, es sollte ein Kommentar sein, der besagt, dass Sie beim Ausführen eine andere Ausgabe erhalten. Ich sehe nicht, dass diese Antwort irgendein Wissen beisteuert. Zumindest eine Erklärung in Verbindung mit der Ausgabe ist immer noch ein wertvoller Beitrag. – Unni