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