Python线程中start与run方法的区别及常见误区解析

方予
方予
发布时间:2026-10-15 | 4人浏览过
原创

本文深入解析Python中Thread类的start与run方法执行机制。start负责创建新线程并调用内部_bootstrap流程,最终执行run;而直接调用run仅在当前线程执行。重点指出一个常见错误:在__init__中直接调用target函数会导致其在主线程执行且返回None,致使线程无法运行。通过源码分析澄清这一误区,帮助开发者正确理解线程生命周期。

start与run方法的核心区别

核心结论:在Python线程机制中,调用start方法启动线程时,若已指定target参数且未重写run方法,线程将直接执行target所指向的方法。

线程启动的底层执行流程

具体实现逻辑如下:首先,需要初始化一个线程对象。

threading.Thread.__init__(self,target=thread_run())

def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, *, daemon=None):
        assert group is None, "group argument must be None for now"
        if kwargs is None:
            kwargs = {}
        self._target = target
        self._name = str(name or _newname())
        self._args = args
        self._kwargs = kwargs

其次,调用start方法以启动该线程。此时,系统内部会调用_start_new_thread函数,并将self._bootstrap作为回调函数传入。

thread1.start()
    def start(self):
        if not self._initialized:
            raise RuntimeError("thread.__init__() not called")
        if self._started.is_set():
            raise RuntimeError("threads can only be started once")
        with _active_limbo_lock:
            _limbo[self] = self
        try:
            _start_new_thread(self._bootstrap, ())
        except Exception:
            with _active_limbo_lock:
                del _limbo[self]
            raise
        self._started.wait()

_start_new_thread的作用等同于启动一个全新的操作系统线程,并在该新线程中执行传入的回调函数。

_start_new_thread = _thread.start_new_thread
def start_new_thread(function: Callable[..., Any], args: tuple[Any, ...], kwargs: dict[str, Any] = ...) -> int: ...

上述传入的回调函数即为前文提到的self._bootstrap。该_bootstrap方法内部会进一步调用_bootstrap_inner(),而_bootstrap_inner最终会调用用户的run方法。

def _bootstrap_inner(self):
    try:
        self._set_ident()
        self._set_tstate_lock()
        if _HAVE_THREAD_NATIVE_ID:
            self._set_native_id()
        self._started.set()
        with _active_limbo_lock:
            _active[self._ident] = self
            del _limbo[self]

        if _trace_hook:
            _sys.settrace(_trace_hook)
        if _profile_hook:
            _sys.setprofile(_profile_hook)
        try:
            self.run()

因此,整个调用链的最终落脚点是执行run方法。

 def run(self):
        try:
            if self._target:
                self._target(*self._args, **self._kwargs)
        finally:
            # Avoid a refcycle if the thread is running a function with
            # an argument that has a member that points to the thread.
            del self._target, self._args, self._kwargs

run方法的执行判定逻辑

总结run方法的执行逻辑:如果用户重写了run方法,则直接执行重写后的run逻辑;如果未重写run方法,但定义了target参数,则执行创建线程时指定的target方法;若两者均未定义,则线程执行空操作。

target参数常见错误用法分析

在实际开发中常遇到一个典型问题:当指定target参数时,打印出的线程名显示为MainThread(主线程),而非预期的子线程名。导致这一现象的代码通常形如:threading.Thread.__init__(self, target=thread_run())。经分析,这是因为在__init__中直接赋值target时,实际上是在主线程中执行了thread_run函数。执行结束后,将thread_run的返回值赋给target参数。由于thread_run没有显式返回值,target变为None。若此时未重写run函数,线程启动后将无任何操作。关键在于,thread_run的执行发生在主线程,而非预期的子线程中。

def thread_run():
    print ("overwrite: 开始线程:" + threading.current_thread().name)
    time.sleep(2)
    print ("overwrite: 退出线程:" + threading.current_thread().name)

class myThread (threading.Thread):
    def __init__(self, threadID, name, delay):
        threading.Thread.__init__(self,target=thread_run())
        self.threadID = threadID
        self.name = name
        self.delay = delay
        thread1.start()

thread1.join()
print ("退出主线程")

上述错误代码的运行结果如下:

overwrite: 开始线程:MainThread overwrite: 退出线程:MainThread 退出主线程

至此,关于Python中start和run方法区别及相关误区的讲解完毕。如需了解更多Python start和run相关内容,建议查阅本站过往文章或继续浏览后续教程,感谢支持。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表