为什么当主线程运行无限循环时,在另一个线程中导入模块要花很长时间?



我有以下Python代码:

import threading
from datetime import datetime
import time
def f():
    print('---- {:%H:%M:%S}'.format(datetime.now()))
    import http.server
    print('---- {:%H:%M:%S}'.format(datetime.now()))
threading.Thread(target=f).start()
while True:
    pass

当我执行它时,我看到import http.server占用了大量时间。从下面的输出中可以看到,导入需要23秒才能完成。

C:>python foo.py
---- 10:12:03
---- 10:12:26

但是,如果我在无限的while循环中设置一点睡眠,则导入会进行得更快。

import threading
from datetime import datetime
import time
def f():
    print('---- {:%H:%M:%S}'.format(datetime.now()))
    import http.server
    print('---- {:%H:%M:%S}'.format(datetime.now()))
threading.Thread(target=f).start()
while True:
    time.sleep(1)
输出:

C:>python foo.py
---- 10:15:58
---- 10:15:58

我知道join()方法的使用,但我想确切地知道为什么当无限的while循环中没有睡眠语句时,import http.server需要这么长时间。

CPython使用全局解释器锁来保护解释器上下文。这可以防止线程同时运行。实际上它们都在单个处理器核心上运行。在CPython中,当线程执行类似空闲的操作时,例如等待io或监听套接字时,您可以受益于线程。
你为主线程做了很多工作。虽然pass没有做什么有趣的事情,但它消耗CPU周期,并且解释器认为为该线程提供CPU时间很重要。
如果是sleep,则写成don't waste anything for this thread until time expires

我不是这个主题的专家,但据我所知,多个线程一个接一个地运行在同一个核心上,所以这是一个CPU时间共享的问题。然后将sleep添加到无限循环中,将为导入线程提供更多资源。要并行运行,请使用多处理。那么您的代码将使用多个核心。您可以查看这个简单的示例

最新更新