python中的多线程

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

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

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

多线程版本代码:

#!/usr/bin/env python

import threading
from time import time

def foo(n):
	if n < 2:
		return 1
	return foo(n - 2) + foo(n - 1)

def main():
	threads = []
	n_process = 8
	n = 36

	for 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 python

from time import time

def foo(n):
	if n < 2:
		return 1
	return foo(n - 2) + foo(n - 1)

def main():
	n_process = 8
	n = 36

	start = 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.)著;孙波翔,李斌,李晗译.

你可能感兴趣的:(小问题,Python,python,多线程)