Seite 1 von 1

Threading.join

Verfasst: Donnerstag 12. Februar 2015, 20:44
von blackno666
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

Re: Threading.join

Verfasst: Donnerstag 12. Februar 2015, 20:48
von Sirius3
@blackno666: was meinst Du ist 't' und was macht die join-Methode dieses 't's?

Re: Threading.join

Verfasst: Donnerstag 12. Februar 2015, 20:51
von blackno666
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)

Re: Threading.join

Verfasst: Donnerstag 12. Februar 2015, 20:53
von Sirius3
Bingo.

Re: Threading.join

Verfasst: Donnerstag 12. Februar 2015, 21:58
von pillmuncher
@blackno666: Und wenn du collections.deque oder queue.Queue verwendest statt [], dann brauchst du dich um das Locking nicht mehr selber zu kümmern.

Re: Threading.join

Verfasst: Donnerstag 12. Februar 2015, 22:13
von EyDu
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.