[TOC]python
從名字上看能告訴咱們不少東西,很顯然,這是一個加在解釋器上的全局(從解釋器的角度看)鎖(從互斥或者相似角度看)。編程
首先來看回顧一下什麼是鎖:安全
因爲多線程共享進程的資源和地址空間,所以,在對這些公共資源進行操做時,爲了防止這些公共資源出現異常的結果,必須考慮線程的同步和互斥問題。多線程
一、用於非線程安全,二、控制一段代碼,確保其不產生調度混亂。spa
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)線程
在CPython中,全局解釋器鎖(global interpreter lock, GIL)是一個互斥體,它防止多個本機線程同時執行Python字節碼。這個鎖是必要的,主要是由於CPython的內存管理不是線程安全的。(然而,自從GIL存在以來,其餘特性已經逐漸依賴於它強制執行的保證。)設計
從上文的介紹和官方的定義來看,GIL就是一把全局排他鎖。這種方式固然很安全,可是這對於任何Python程序來講,無論有多少的處理器,任什麼時候候都老是隻有一個線程在執行。毫無疑問全局鎖的存在會對多線程的效率有不小影響。code
可是咱們課上講的例子,並非這樣啊接口
上課的多線程例子:進程
from threading import Thread import time def task(): time.sleep(5) def run(): t1 = Thread(target=task) t2 = Thread(target=task) start = time.time() t1.start() t1.join() t2.start() t2.join() end = time.time() print(f'Total time: {end - start}') ''' 串行結果: Total time:10 ''' t1.start() t2.start() t1.join() t2.join() ''' 並行結果: Total time:5 '''
可是!
看看這個
from threading import Thread import time def counter(): # 計數到一億 i = 0 for _ in range(100000000): i += 1 return True def run(): t1 = Thread(target=counter) t2 = Thread(target=counter) start = time.time() t1.start() t1.join() t2.start() t2.join() end = time.time() print(f'Total time: {end - start}') ''' 串行結果(即單線程): Total time: 15.838918209075928 ''' t1.start() t2.start() t1.join() t2.join() ''' 並行結果: Total time: 16.79609990119934 (其實他們兩個結果我跑的時候不相上下,可是也能說明問題) ''' if __name__ == '__main__': run()
問題來了。
爲何多線程並行比單線程慢,可是老師講的例子爲何多線程並行時間又更少?
剛剛也說了是由於GIL致使的,python解釋器任什麼時候候都是一個線程在執行。
課上例子多線程並行快的緣由是: 線程作的是i/o操做, 能夠掛起當前線程去執行下一線程。由於遇到像 i/o操做這種 會有時間空閒狀況 形成cpu閒置的狀況會釋放GIL
因此在python上只要在進行耗時的IO操做的時候,能釋放GIL,這樣也仍是能夠提高運行效率的。
改不了!
歷史遺留問題:由於硬件的升級cpu單核變多核,當時python開發者爲了利用多核,就出現了多線程編程,而隨之帶來的就是線程間數據一致性和狀態同步的困難。 python開發者的解決方法就是加GIL這把大鎖。
可是人們以後發現了這種多線程編程實現方式是垃圾的,想去除他,可是這時候已經發現離不開他了,大量的開發者已經重度依賴GIL了。
一、進程能夠利用多核,可是開銷大。
二、多線程開銷小,卻沒法利用多核優點。
也就是說Python中的多線程是假的多線程,Python解釋器雖然能夠開啓多個線程,但同一時間只有一個線程能在解釋器中執行,而作到這一點正是因爲GIL鎖的存在,它的存在使得CPU的資源同一時間只會給一個線程使用,而因爲開啓線程的開銷小,因此多線程纔能有一片用武之地,否則就真的是雞肋了。
而python的多線程到底有沒有用呢?
有用。咱們須要看任務是I/O密集型,仍是計算密集型:
若是是I/O密集型任務,有再多核也沒用,即能開再多進程也沒用,因此咱們利用python的多線程一點問題也沒有;
若是是計算密集型任務,咱們就直接使用多進程就能夠了
一、不用cpython,使用jpython(不太可能)
二、使用多進程完成多線程任務(python專家推薦)
用multiprocess來代替Thread
multiprocess庫的出現很大程度上是爲了彌補thread庫由於GIL而低效的缺陷。它完整的複製了一套thread所提供的接口方便遷移。惟一的不一樣就是它使用了多進程而不是多線程。每一個進程有本身的獨立的GIL,所以也不會出現進程之間的GIL爭搶。
可是它的引入會增長程序實現時線程間數據通信和同步的困難。
三、使用多線程時用c語言實現 (還要學c,我可去他的)