Uso de roscado.Hilo.unir()


Soy nuevo en multithreading en python e intento aprender multithreading usando el módulo threading. He hecho un programa muy simple de multi threading y estoy teniendo problemas para entender el método threading.Thread.join.

Aquí está el código fuente del programa que he hecho

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() 

¿Qué diferencia hay si utilizo

thread1.join()
thread2.join()

Que he comentado en el código anterior? Ejecuté los dos códigos fuente (uno con comentarios y el otro sin comentarios), pero la salida es la igual.

Author: Erik Allik, 2013-10-02

3 answers

Una llamada a thread1.join() bloquea el hilo en el que estás haciendo la llamada, hasta que thread1 esté terminado. Es como wait_until_finished(thread1).

Por ejemplo:

import time

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

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

Impresiones

hello
hello
hello
goodbye

-sin la llamada .join(), goodbye vendría primero y luego 3 * hello.

También, tenga en cuenta que los subprocesos en Python no proporcionan ningún rendimiento adicional (en términos de potencia de procesamiento de la CPU) debido a una cosa llamada Global Interpreter Lock, por lo que si bien son útiles para generar potencialmente bloqueando (por ejemplo, IO, red) y tareas que consumen mucho tiempo (por ejemplo, procesamiento de números) para mantener el subproceso principal libre para otras tareas, no le permiten aprovechar múltiples núcleos o CPU; para eso, mire multiprocessing que usa subprocesos pero expone una API equivalente a la de threading.

PLUG: ...y también es por la razón anterior que, si usted está interesado en la concurrencia, es posible que también desee buscar en una biblioteca fina llamada Gevent, que esencialmente sólo hace el enhebrado es mucho más fácil de usar, mucho más rápido (cuando tiene muchas actividades concurrentes) y menos propenso a errores relacionados con la concurrencia, al tiempo que le permite seguir codificando de la misma manera que con los subprocesos "reales". También Twisted, Eventlet, Tornado y muchos otros, son equivalentes o comparables. Además, en cualquier caso, yo sugeriría fuertemente la lectura de estos clásicos:

 64
Author: Erik Allik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-19 18:26:24

He modificado el código para que entiendas exactamente cómo funciona join. así que ejecute este código con comentarios y sin comentarios y observe la salida para ambos.

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
Author: aaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-01 22:37:37

Como la documentación relevante indica, join hace que el llamador espere hasta que el hilo termine.

En su caso, la salida es la misma porque join no cambia el comportamiento del programa - probablemente se está utilizando para salir del programa limpiamente, solo cuando todos los subprocesos han terminado.

 1
Author: goncalopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-02 13:42:35