標準的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是不會影響系統調用的
。