web-dev-qa-db-fra.com

Utilisation de threading.Thread.join ()

Je suis nouveau dans le multithreading en python et j'essaie d'apprendre le multithreading en utilisant le module de threading. J'ai créé un programme très simple de multi threading et j'ai du mal à comprendre le threading.Thread.join méthode.

Voici le code source du programme que j'ai réalisé

import threading

val = 0

def increment():
   global val 
   print "Inside increment"
   for x in range(100):
       val += 1
   print "val is now {} ".format(val)

thread1 = threading.Thread(target=increment, args=())
thread2 = threading.Thread(target=increment, args=())
thread1.start()
#thread1.join()
thread2.start()
#thread2.join() 

Quelle différence cela fait-il si j'utilise

thread1.join()
thread2.join()

que j'ai commenté dans le code ci-dessus? J'ai exécuté les deux codes source (un avec des commentaires et un sans commentaires) mais la sortie est la même.

24
Pratik Singhal

Un appel à thread1.join() bloque le thread dans lequel vous effectuez l'appel, jusqu'à ce que thread1 Soit terminé. C'est comme wait_until_finished(thread1).

Par exemple:

import time

def printer():
    for _ in range(3):
        time.sleep(1.0)
        print "hello"

thread = Thread(target=printer)
thread.start()
thread.join()
print "goodbye"

impressions

hello
hello
hello
goodbye

—Sans l'appel .join(), goodbye viendrait en premier, puis 3 * hello.

Notez également que les threads de Python ne fournissent aucune performance supplémentaire (en termes de puissance de traitement du processeur) en raison d'une chose appelée Global Interpreter Lock , donc pendant qu'ils sont utiles pour engendrer des tâches potentiellement bloquantes (par exemple IO, réseau) et chronophages (par exemple, la compression des nombres) pour garder le thread principal libre pour d'autres tâches, elles ne vous permettent pas d'exploiter plusieurs cœurs ou processeurs; pour cela, regardez multiprocessing qui utilise des sous-processus mais expose une API équivalente à celle de threading.

PLUG: ... et c'est aussi pour la raison ci-dessus que, si vous êtes intéressé par la concurrence, vous voudrez peut-être aussi examiner une amende bibliothèque appelée Gevent, qui rend essentiellement le threading beaucoup plus facile à utiliser, beaucoup plus rapide (lorsque vous avez de nombreuses activités simultanées) et moins sujet aux bogues liés à la concurrence, tout en vous permettant de continuer à coder de la même manière qu'avec les "vrais" threads. Twisted, Eventlet, Tornado et bien d'autres sont également équivalents ou comparables. De plus, dans tous les cas, je vous suggère fortement de lire ces classiques:

65
Erik Allik

J'ai modifié le code pour que vous compreniez comment fonctionne exactement join. exécutez donc ce code avec des commentaires et sans commentaires et observez la sortie pour les deux.

val = 0

def increment(msg,sleep_time):
   global val 
   print "Inside increment"
   for x in range(10):
       val += 1
       print "%s : %d\n" % (msg,val)
       time.sleep(sleep_time)

thread1 = threading.Thread(target=increment, args=("thread_01",0.5))
thread2 = threading.Thread(target=increment, args=("thread_02",1))
thread1.start()
#thread1.join()
thread2.start()
#thread2.join()
4
aaj

Comme la documentation appropriée indique, join fait attendre l'appelant jusqu'à ce que le thread se termine.

Dans votre cas, la sortie est la même parce que join ne change pas le comportement du programme - il est probablement utilisé pour quitter le programme proprement, uniquement lorsque tous les threads sont terminés.

1
goncalopp