使用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的目的是啥的主要内容,如果未能解决你的问题,请参考以下文章

Java Thread.join的作用和原理

使用 threading.Thread.join()

std::thread.join() 做啥?

Thread中的join使用

boost - thread.join() 停止用户界面

join的简单总结