标准的Python实现叫做CPython
。CPython
分两步用来运行Python程序:
- 1.首先,将文本形式的源代码解析并编译成字节码;
- 2.然后,用一种基于栈的解释器运行这份字节码。
执行Python程序时,字节码解释器必须保持协调一直的状态。Python采用全局解释器锁(GIL
)机制来实现这种协调性。
GIL
实际上是一把互斥锁
,用来防止CPython
受到抢占式多线程切换操作的干扰。但是,GIL
有一个显著的缺点在于,C++
和Java
等语言的多线程程序可以充分利用CPU
的多核,而Python编写的多线程程序,受到GIL
保护,同一时刻,只有一条线程可以执行
。
案例1:利用Python进行因数分解算法。
from time import time
def factorize(number):
for i in range(1, number+1):
if number % i == 0:
yield i
if __name__ == '__main__':
numbers = [2149000, 3902300, 8390202, 10008375]
start = time()
for number in numbers:
list(factorize(number))
end = time()
print("Spend time %.3f seconds" % (end-start))
输出结果:
Spend time 2.022 seconds
改成使用Python的多线程程序:
from threading import Thread
from time import time
def factorize(number):
for i in range(1, number+1):
if number % i == 0:
yield i
class FactorizeThread(Thread): ##继承Thread
def __init__(self,number):
super().__init__()
self.number = number
def run(self):
self.factors = list(factorize(self.number))
if __name__ == '__main__':
numbers = [2149000, 3902300, 8390202, 10008375]
start = time()
threads = []
for number in numbers:
thread = FactorizeThread(number)
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
end = time()
print('Spend time %.3f seconds' %(end-start))
输出结果:
Spend time 2.570 seconds
可以看出,多线程程序执行所花费的时间竟然更长。这样的结果表明,标准的CPython
解释器的多线程程序受到GIL
的影响。
尽管Python的多线程很鸡肋,但是仍然可以应用在阻塞式的IO操作中,例如读写文件,网络通讯等操作。同时,Python在多个线程中执行系统调用
时,其可以实现平行地执行。Python线程在执行系统调用的时候会释放GIL锁,并且一直等到执行完毕才会重新获取它,所以GIL是不会影响系统调用的
。