26

我是 python 中的多线程新手,并尝试使用 threading 模块学习多​​线程。我制作了一个非常简单的多线程程序,但我无法理解该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()

我在上面的代码中评论了什么?我运行了两个源代码(一个有注释,一个没有注释),但输出是一样的。

4

3 回答 3

67

调用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 中的线程不会提供任何额外的性能(就 CPU 处理能力而言),因为有一个叫做Global Interpreter Lock的东西,所以虽然它们对于产生潜在的阻塞(例如 IO、网络)和耗时很有用任务(例如数字运算)以保持主线程空闲用于其他任务,它们不允许您利用多个内核或 CPU;为此,请查看multiprocessing哪些使用子流程但公开了与threading.

PLUG: ...而且也是出于上述原因,如果您对并发感兴趣,您可能还想研究一个名为 Gevent 的优秀库,它本质上只是使线程更易于使用,更快(当您有许多并发活动)并且不太容易出现与并发相关的错误,同时允许您保持与“真实”线程相同的编码方式。此外,Twisted、Eventlet、Tornado 和许多其他的都是等效的或可比的。此外,无论如何,我强烈建议阅读这些经典:

于 2013-10-02T13:41:23.160 回答
5

我修改了代码,以便您了解 join 的工作原理。所以运行这段代码,带注释和不带注释,并观察两者的输出。

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()
于 2013-10-03T06:10:48.843 回答
1

正如相关文档所述,join使调用者等待线程终止。

在您的情况下,输出是相同的,因为join不会改变程序行为 - 它可能被用来干净地退出程序,只有当所有线程都终止时。

于 2013-10-02T13:42:35.330 回答