python中的多线程

python代码的执行是由python虚拟机进行控制的。尽管python解释器中可以运行多个线程,但是在任意给定时刻只有一个线程会被解释器执行。

python虚拟机的访问是由全局解释器锁(GIL)控制的。这个锁就是用来保证同时只能有一个线程运行的。因此,在 python中无法通过多线程来利用多个 CPU同时处理任务,以达到应用加速的目的。下面通过两个测试程序可以验证这个问题。

我的处理器有 8个核,因此在多线程测试中一共创建 8个线程来处理任务,这里的任务特指:使用递归求解斐波拉契数。

多线程版本代码:

#!/usr/bin/env pythonimport threading
from time import timedef foo(n):if n < 2:return 1return foo(n - 2) + foo(n - 1)def main():threads = []n_process = 8n = 36for i in range(0, n_process):t = threading.Thread(target=foo, args=(n,))threads.append(t)start = time()for i in range(0, n_process):threads[i].start()for i in range(0, n_process):threads[i].join()end = time()print("start: %f, end: %f, cost: %f" % (start, end, end - start))if __name__ == "__main__":main()

运行时间:

$ python3 ./python/multi_thread/main.py
start: 1687413176.686146, end: 1687413199.358464, cost: 22.672318

单线程版本代码:

#!/usr/bin/env pythonfrom time import timedef foo(n):if n < 2:return 1return foo(n - 2) + foo(n - 1)def main():n_process = 8n = 36start = time()for i in range(0, n_process):foo(n)end = time()print("start: %f, end: %f, cost: %f" % (start, end, end - start))if __name__ == "__main__":main()

运行时间:

$ python3 ./python/multi_thread/main2.py
start: 1687413202.103315, end: 1687413223.906954, cost: 21.803639

从上面的例子可以看到,由于 python虚拟机是单线程(GIL)的原因,对于计算密集型任务,多线程无法起到应用加速的目的,只有程序在执行I/O密集型的任务时才能更好地发挥 python多线程的并发行(I/O释放了GIL,可以允许更多的并发)。对于计算密集型任务,为了实现更好的并行性,需要使用多进程,以便让 CPU的其他核来同时处理任务。

参考资料:
Python核心编程:第3版 /(美)春(Chun, W.)著;孙波翔,李斌,李晗译.

本文链接:https://my.lmcjl.com/post/10337.html

展开阅读全文

4 评论

留下您的评论.