什么是GLI?
Python中的線程是操作系統的原生線程,Python虛擬機使用一個全局解釋器鎖(Global Interpreter Lock)來互斥線程對Python虛擬機的使用。為了支持多線程機制,一個基本的要求就是需要實現不同線程對共享資源訪問的互斥,所以引入了GIL。由於GLI的存在,一個線程擁有了解釋器的訪問權之后,其他的所有線程都必須等待它釋放解釋器的訪問權,即使這些線程的下一條指令並不會互相影響。在調用任何Python C API之前,都要先獲得GIL。
GLI特點
- 缺點:多處理器退化為單處理器
- 優點:避免大量的加鎖解鎖操作
GIL作用
無論你啟多少個線程,你有多少個cpu, Python在執行一個進程的時候會淡定的在同一時刻只允許一個線程運行。所以,python是無法利用多核CPU實現多線程的。這樣,python對於計算密集型的任務開多線程的效率甚至不如串行(沒有大量切換),但是對於IO密集型的任務效率還是有顯著提升的。
GLI 與 Lock
GIL保護的是解釋器級的數據,保護用戶自己的數據則需要自己加鎖處
GIL與多線程
python解釋器因為GIL的存在,在同一時刻同一進程中只有一個線程被執行。如何解決這一問題
首先明確一下三點:
- cpu到底是用來做計算的,還是用來做I/O的?
- 多cpu,意味着可以有多個核並行完成計算,所以多核提升的是計算性能
- 每個cpu一旦遇到I/O阻塞,仍然需要等待,所以多核對I/O操作沒什么用處
舉例:一個工人相當於cpu,此時計算相當於工人在干活,I/O阻塞相當於為工人干活提供所需原材料的過程,工人干活的過程中若沒有原材料,則工人干活的過程需要停止,直到等待原材料的到來。如果你的工廠干的大多數任務都要有准備原材料的過程(I/O密集型),則有再多的工人,意義也不大,還不如一個人,在等材料的過程然后讓工人去做別的事情,反過來講,如果你的工廠原材料都齊全,那當然是工人越多,效率越高。由此可以得出結論:對計算來說,cpu越多越好,但是對於I/O來說,再多的cpu也沒用當然對運行一個程序來說,隨着cpu的增多執行效率肯定會有所提高(不管提高幅度多大,總會有所提高),這是因為一個程序基本上不會是純計算或者純I/O,所以我們只能相對的去看一個程序到底是計算密集型還是I/O密集型,從而進一步分析python的多線程到底有無用武之地.
多進程計算密集型

from multiprocessing import Process from threading import Thread import os,time def work(): res=0 for i in range(100000000): res*=i if __name__ == '__main__': l=[] print(os.cpu_count()) #本機為4核 start=time.time() for i in range(4): p=Process(target=work) #耗時5s多 p=Thread(target=work) #耗時18s多 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start))
多線程IO密集型

from multiprocessing import Process from threading import Thread import threading import os,time def work(): time.sleep(2) print('===>') if __name__ == '__main__': l=[] print(os.cpu_count()) #本機為4核 start=time.time() for i in range(400): # p=Process(target=work) #耗時12s多,大部分時間耗費在創建進程上 p=Thread(target=work) #耗時2s多 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start))
並行與並發
- 並行處理:(Parallel Processing):是計算機系統中能同時執行兩個或更多個處理的一種計算方法。並行處理可同時工作於同一程序的不同方面。並行處理的主要目的是節省大型和復雜問題的解決時間。
- 並發處理(concurrency Processing):指一個時間段中有幾個程序都處於已啟動運行到運行完畢之間,且這幾個程序都是在同一個處理機(CPU)上運行,但任一個時刻點上只有一個程序在處理機(CPU)上運行
ps:並發的關鍵是你有處理多個任務的能力,不一定要同時。並行的關鍵是你有同時處理多個任務的能力。因而並行是並發的子集.
同步與異步
- 同步:就是指一個進程在執行某個請求的時候,若該請求需要一段時間才能返回信息,那么這個進程將會一直等待下去,直到收到返回信息才繼續執行下去
- 異步:是指進程不需要一直等下去,而是繼續執行下面的操作,不管其他進程的狀態。當有消息返回時系統會通知進程進行處理,這樣可以提高執行的效率
ps:打電話時就是同步通信,發短息時就是異步通信。