Threading.join

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
blackno666
User
Beiträge: 2
Registriert: Donnerstag 12. Februar 2015, 20:38

Hallo,

ich habe eine Verständnisfrage zum multi-threading. Ich habe folgendes Programm:

Code: Alles auswählen

import time
from threading import Thread
import random

d = []

def do(i):
    time.sleep(random.random())
    d.append(i)

for i in range(10):
    t = Thread(target=do, args=(i,))
    t.start()

t.join()
print(d)
Ich hätte erwartet, dass meine Ausgabe eine list mit 10 Elementen (ungeordnet) zurück liefert. Allerdings ist die Liste zufällig lang.

Gut. Ich habe mein d ja nicht geschützt, also habe ich versucht, dies über eine lock zu machen:

Code: Alles auswählen

import time
from threading import Thread
import random
import threading

d = []

def do(i, l):
    time.sleep(random.random())
    l.acquire()
    d.append(i)
    l.release()

lock = threading.Lock()

for i in range(10):
    t = Thread(target=do, args=(i,lock,))
    t.start()

t.join()
print(d)
Auch das bringt mir nichts. Ich erhalte jetzt meist eine noch kürzere Liste zurück.

Mein Verständnis war, dass join die Ausführung meines Haupt-Threads so lange verzögert, bis alle Threads sich beendet haben und dann erst d ausgegeben wird. Irgendwo stimmt diese Überlegung offensichtlich nicht.

Über alle Hinweise bin ich dankbar.

blackno666
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@blackno666: was meinst Du ist 't' und was macht die join-Methode dieses 't's?
blackno666
User
Beiträge: 2
Registriert: Donnerstag 12. Februar 2015, 20:38

Wenn du so fragst, dann glaube ich, dass t der letzte von 10 gestarteten Threads ist und ich nur auf den letzten warte...?

So korrekt?

Code: Alles auswählen

import time
from threading import Thread
import random
import threading

d = []

def do(i, l):
    time.sleep(random.random())
    l.acquire()
    d.append(i)
    l.release()

lock = threading.Lock()

at = []

for i in range(10):
    t = Thread(target=do, args=(i,lock,))
    at.append(t)
    t.start()

for i in range(len(at)):
    at[i].join()
    
print(d)
Zuletzt geändert von blackno666 am Donnerstag 12. Februar 2015, 20:53, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

Bingo.
Benutzeravatar
pillmuncher
User
Beiträge: 1532
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@blackno666: Und wenn du collections.deque oder queue.Queue verwendest statt [], dann brauchst du dich um das Locking nicht mehr selber zu kümmern.
In specifications, Murphy's Law supersedes Ohm's.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du solltest in Python direkt über die Elemente einer Liste iterieren, die Generierung eines Index ist ein Anti-Pattern. Verwende statt

Code: Alles auswählen

for i in range(len(at)):
    at[i].join()
also

Code: Alles auswählen

for thread in at:
    thread.join()
Wenn du doch mal einen Index benötigst, dann hilft dabei die enumerate-Funktion. Wenn du über mehrere Sequenzen parallel iterierst, dann verwende die zip-Funktion.
Das Leben ist wie ein Tennisball.
Antworten