我有一个查询。我见过开发人员编写类似代码的示例,如下所示:
import threading
def do_something():
return true
t = threading.Thread(target=do_something)
t.start()
t.join()
字符串
我知道join()
会通知解释器等待线程完全执行,但是如果我不写t.join()
呢?线程会自动关闭,以后会被重用吗?
这是我第一次尝试用Python 3.5.0创建多线程应用程序。
我有一个查询。我见过开发人员编写类似代码的示例,如下所示:
import threading
def do_something():
return true
t = threading.Thread(target=do_something)
t.start()
t.join()
字符串
我知道join()
会通知解释器等待线程完全执行,但是如果我不写t.join()
呢?线程会自动关闭,以后会被重用吗?
这是我第一次尝试用Python 3.5.0创建多线程应用程序。
4条答案
按热度按时间djp7away1#
Python线程只是一个普通的操作系统线程。如果你不加入它,它仍然会与当前线程并发运行。当目标函数完成或引发异常时,它最终会死亡。不存在“线程重用”这样的事情,一旦它死亡,它就会安息。
除非线程是一个“守护线程”(通过构造函数参数
daemon
或分配daemon
属性),否则它将在程序退出前被隐式连接,否则,它会被突然杀死。在Python中编写多线程程序时需要记住的一件事是,由于臭名昭著的Global interpreter lock,它们的使用有限。简而言之,使用线程不会使CPU密集型程序更快。它们只有在执行涉及等待的操作时才有用(例如,等待线程中发生某些文件系统事件)。
yb3bgrhw2#
join
部分意味着主程序将等待线程结束后再继续。如果没有join,主程序将结束,线程将继续。现在,如果您将
daemon
参数设置为“True”,则意味着线程将依赖于主程序,并且如果主程序在此之前结束,则线程将结束。这里有一个例子来更好地理解:
字符串
没有守护进程,没有加入:
型
仅daemon:
型
仅加入:
型
daemon和join:
型
chhkpiq43#
join()
**,非守护进程线程将运行,并与主线程并发完成。join()
**,守护线程将与主线程并发运行,当主线程完成时,如果守护线程仍在运行,则守护线程将退出而不完成。你可以在this post中看到我的答案详细解释。
unhi4e5o4#
在Python 3.10.12中,如果你不使用
join()
线程,没有什么不好的事情发生。为了测试,我使用了以下代码:字符串
在启动此代码后的前20秒内,您可以使用
ps -eLf
,ls /proc/MAINPROCESSID/task
和许多其他命令来验证,在此测试应用程序中实际上有52个线程正在运行:主线程,50个前台子线程和守护线程。启动应用程序后20秒,前台子线程全部退出,只剩下两个线程:主线程和守护线程.ps -eLf
没有显示任何未读状态或类似状态的“僵尸线程”,因此没有操作系统资源被未加入的线程阻塞!当总时间超过40秒时,主线程也退出,守护线程也完成,python应用程序退出。因此未加入的线程也不会阻塞Python内部的任何资源,特别是,它们不会让守护线程不必要地运行。
只有一个建议:如果你打算永远不加入线程,不要保留对周围创建的线程的引用,这样python解释器就可以完成它的工作,并垃圾收集与所有完成的线程相关的所有资源。测试应用程序
threading.Thread(target=..., args=...).start()
中的语法是实现这种“发射并忘记”语义的一种可能方法。当然,请确保使用其他同步方法(如
threading.mutex
或threading.semaphore
)来跟踪线程的工作。