Uso de enhebrado.Thread.join ()

Soy nuevo en multihilo en python y trato de aprender multihilo utilizando el módulo de subprocesamiento. He creado un progtwig muy simple de subprocesos múltiples y tengo problemas para entender el método de threading.Thread.join .

Aquí está el código fuente del progtwig 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 hace si uso

 thread1.join() thread2.join() 

¿Qué he comentado en el código anterior? Corrí los códigos fuente (uno con comentarios y el otro sin comentarios) pero la salida es la misma.

Una llamada a thread1.join() bloquea el hilo en el que está haciendo la llamada, hasta que thread1 . 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" 

huellas dactilares

 hello hello hello goodbye 

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

Además, 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 Intérprete Lock , por lo que son útiles para generar posibles lockings (por ejemplo, IO, red) y requieren mucho tiempo. las tareas (p. ej., procesamiento de números) para mantener el hilo principal libre para otras tareas, no le permiten aprovechar múltiples núcleos o CPU; para eso, observe el multiprocessing que utiliza subprocesos pero expone una API equivalente a la de threading .

PLUG: … y es también por la razón anterior que, si estás interesado en la concurrencia, también deberías buscar en una biblioteca fina llamada Gevent, que esencialmente hace que el subprocesamiento sea 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, mientras 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, sugiero encarecidamente leer estos clásicos:

  • Generador de trucos para progtwigdores de sistemas
  • Un curso curioso sobre coroutines y concurrencia.

He modificado el código para que entiendas cómo funciona exactamente unirte. ejecute este código con comentarios y sin comentarios y observe el resultado de 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() 

Como indica la documentación relevante , join hace que la persona que llama espere hasta que finalice el hilo.

En su caso, la salida es la misma porque join no cambia el comportamiento del progtwig; probablemente se esté utilizando para salir del progtwig limpiamente, solo cuando todos los subprocesos hayan terminado.