使用Join with threading的目的是啥
Posted
技术标签:
【中文标题】使用Join with threading的目的是啥【英文标题】:What is the purpose of using Join with threading使用Join with threading的目的是什么 【发布时间】:2022-01-16 14:54:03 【问题描述】:当使用线程时,您正在寻找同时快速执行多个实例,.join() 不会通过等待每个线程在开始之前完成来破坏该目的,这在本质上不是准确的吗与常规循环相同。当不使用 join 时,线程会在启动时尽快触发。我的问题可能听起来很幼稚,因为我还在努力学习。
假设 itemsArr 有 1000 个项目,itemQueryRequest 需要 3 秒来执行, 您希望每个项目尽可能接近相同的查询 时间到了,所以你可以使用线程。
此外,一旦目标函数完成,无论加入,线程都会死亡,所以你..我错过了什么。
#lightning fast
import threading
for item in itemsArr:
t = Thread(target=itemQueryRequest, args=(item,))
t.start()
# SLOW
th = []
for item in itemsArr:
t = Thread(target=itemQueryRequest, args=(item,))
th.append(t)
th.start()
th.join() // < SLOW
【问题讨论】:
如果你从来没有join
你的线程,你怎么知道什么时候使用他们计算的值或他们创建的文件?
注意:尽管有这个名字,python 中的threading
模块不提供多线程。
@spectras 怎么不行?
@KellyBundy 由于全局解释器锁,一次只有一个线程可以执行 Python 代码(来自模块的文档)。缺乏适当的线程是 python 的一个众所周知的限制。
@spectras 它提供了有限的多线程形式;例如您的线程可以彼此异步进行,并且您可以同时进行多个阻塞 I/O 操作,这是单个线程无法做到的。尽管如此,如果/何时他们可以摆脱 GIL 并允许 Python 进程使用多个内核的 CPU 周期,那将是一件好事。
【参考方案1】:
你是对的,如果你在启动一个线程后立即调用join()
,它就违背了拥有一个线程的目的,因为现在你有一个子线程正在运行,但你的主线程被阻塞,直到子线程线程返回,因此您仍然没有任何并行性。
但是,join()
不打算以这种方式使用。相反,预计您将start()
一个或多个线程,然后主线程将继续执行(无论它通常做什么),或者它会在每个启动的线程上调用join()
为了阻塞直到所有线程都退出。在这两种情况下,您仍然实现了有效的并行性(尽管有 Python GIL)。
然而,join()
的真正目的是让您安全地释放资源。一方面,在调用join()
(或detach()
)之前,有一些与每个线程相关的底层资源(例如它的返回值)需要保留在内存中,以防父线程想要使用它们;更重要的是,如果父线程分配了一些子线程可以访问的资源,那么在子线程退出之前,父线程释放该资源通常是不安全的,因为在子线程处于中间使用它会给子线程带来很大的问题。
同样,如果子线程正在准备一些数据供父线程使用,那么在子线程完成准备之前,父线程尝试使用该数据是不安全的——没有意义尝试使用半构建数据。
鉴于此,父线程通常调用join()
以等待子线程退出,然后再执行任何会影响子线程的清理工作。
如果子线程没有设计为在有限的时间内自动退出,主线程可能会在调用join()
之前请求子线程退出,例如通过设置布尔变量或在管道上写入字节等,子线程将通过退出对此做出反应,因此join()
调用不会无限期地阻塞。
【讨论】:
以上是关于使用Join with threading的目的是啥的主要内容,如果未能解决你的问题,请参考以下文章