我有以下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添加到无限循环中,将为导入线程提供更多资源。要并行运行,请使用多处理。那么您的代码将使用多个核心。您可以查看这个简单的示例