Подтвердить что ты не робот

Использование threading.Thread.join()

Я новичок в многопоточности в python и пытаюсь изучить многопоточность с использованием модуля потоковой передачи. Я сделал очень простую программу многопоточности, и мне трудно понять метод threading.Thread.join.

Вот исходный код программы, которую я создал

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

Какая разница, если я использую

thread1.join()
thread2.join()

который я прокомментировал в приведенном выше коде? Я запускал оба исходных кода (один с комментариями и один без комментариев), но вывод тот же.

4b9b3361

Ответ 1

Вызов thread1.join() блокирует поток, в котором вы выполняете вызов, до тех пор, пока thread1 не будет завершен. Это нравится wait_until_finished(thread1).

Например:

import time

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

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

печатает

hello
hello
hello
goodbye

- без вызова .join(), сначала будет goodbye, а затем 3 * hello.

Также обратите внимание, что потоки в Python не обеспечивают дополнительной производительности (с точки зрения мощности процессора) из-за вещи, называемой Global Interpreter Lock, так что, хотя они полезны для отсрочки потенциальной блокировки (например, IO, сети) и трудоемких задач (например, хруст числа), чтобы поддерживать основной поток для других задач, они не позволяют использовать несколько ядер или процессоров; для этого просмотрите multiprocessing, который использует подпроцессы, но предоставляет API, эквивалентный API threading.

PLUG:... и по вышеуказанной причине, если вы заинтересованы в concurrency, вам также может понадобиться посмотреть в тонкую библиотеку Gevent, которая по существу просто делает потоки намного проще в использовании, гораздо быстрее (когда у вас много одновременных действий) и менее подвержен ошибкам concurrency, а также позволяет кодировать то же самое, что и с "настоящими" потоками. Также Twisted, Eventlet, Tornado и многие другие эквивалентны или сопоставимы. Кроме того, в любом случае я настоятельно рекомендую прочитать эти классики:

Ответ 2

Я изменил код, чтобы вы поняли, как работает соединение. поэтому запустите этот код с комментариями и без комментариев и посмотрите вывод для обоих.

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

Ответ 3

Как соответствующая документация, join заставляет вызывающего абонента ждать окончания потока.

В вашем случае результат тот же, поскольку join не изменяет поведение программы - он, вероятно, используется для выхода из программы чисто, только когда все потоки завершены.