今天看到一篇文章,講述的是幾個提高python性能的項目:傳送門 python
在看的過程當中,接觸到一個名詞,一個從學python開始就一直看到,可是歷來都是隻知其一;不知其二的名詞,內心不開心,必須把它搞明白,對了,這個詞就是 GIL。網上搜索了一些資料,粗淺的理解了什麼是GIL,本身感受學習的過程比較好,感受略有收穫,老規矩,爲了鞏固知識,本身整片文章出來寫一寫,其實好多文章已經寫的很完善了,因此這篇隨筆,只作知識鞏固,若有雷同,請各位原創做者原諒,小菜鳥一枚,若是哪裏寫的有問題,還請各位前輩不吝指正。linux
一句話:解決多線程之間數據完整性和狀態同步的最簡單方法天然就是加鎖。git
首先,GIL的全名,Global Interpreter Lock
,鑑於英文水平,不作名詞翻譯,以避免誤導。大致解釋一下,這個鎖就是用來爲了解決Cpython多線程中線程不安全問題引入的一個全局排它鎖,它的做用就是在多線程狀況下,保護共享資源,爲了避免讓多個線程同時操做共享資源,致使不可預期的結果而加上的鎖,在一個線程操做共享資源時,其餘線程請求該資源,只能等待GIL解鎖。這個設置在Cpython剛引入多線程概念的時候就有了,而後後續的各類包和組件開發都不可避免的受到了GIL的影響,因此有人會說,python在多線程處理的時候很慢。python GIL實現方式相似於以下僞代碼:github
if __name__ == '__main__': GIL鎖開始運做 主線程作操做 主線程完成操做 GIL鎖釋放資源
因此多線程共同操做共享資源的時候,有一個線程競得了資源,它就被GIL鎖保護起來,其餘線程只能是在那裏等着,可是這個時候,線程的休眠喚醒,所有會消耗CPU資源,因此嘞,就會慢。安全
看到這個時候,我又發現了一個名詞:線程安全。這個名詞,也是那種特別熟悉,但就是沒法清晰的說出它是啥的概念。查了資料,在這記一下:多線程
線程安全就是多線程訪問時,採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其餘線程不能進行訪問直到該線程讀取完,其餘線程纔可以使用。不會出現數據不一致或者數據污染。 線程不安全就是不提供數據訪問保護,有可能出現多個線程前後更改數據形成所獲得的數據是髒數據。併發
我本身想了一下,大約就是這樣,好比整個列表,倆個線程同時在列表中append操做,若是沒有鎖的保護,在機緣巧合之下,倆個線程同時前後申請了空間且沒來得及插入數據,而後這時列表中只會有一個空間,那麼在插入過程當中只能有一個數據寫入,會形成不可知後果,有可能報錯終止,有可能有一個線程操做沒成功,那麼這個就是線程不安全了,大白話說,只要線程之間沒有共享資源,那麼就是線程安全的,有共享資源,爲了保證線程安全,須要引進鎖的機制。app
然後的文章中,有前輩作過實驗:框架
順序執行的單線程(single_thread.py) #! /usr/bin/python from threading import Thread import time def my_counter(): i = 0 for _ in range(100000000): i = i + 1 return True def main(): thread_array = {} start_time = time.time() for tid in range(2): t = Thread(target=my_counter) t.start() t.join() end_time = time.time() print("Total time: {}".format(end_time - start_time)) if __name__ == '__main__': main()
同時執行的兩個併發線程(multi_thread.py) #! /usr/bin/python from threading import Thread import time def my_counter(): i = 0 for _ in range(100000000): i = i + 1 return True def main(): thread_array = {} start_time = time.time() for tid in range(2): t = Thread(target=my_counter) t.start() thread_array[tid] = t for i in range(2): thread_array[i].join() end_time = time.time() print("Total time: {}".format(end_time - start_time)) if __name__ == '__main__': main()
最終結果以下:機器學習
以上測試代碼和圖片引用自:
http://cenalulu.github.io/python/gil-in-python/
過程證實了由於GIL的存在,致使python在使用多線程的時候反而不如順序執行快。
此處我又溫習了一下python線程:
線程的順序執行仍是多線程併發,取決於join函數的位置。join函數的做用是等待當前線程結束,因此每個線程建立以後,調用start函數,這是在後面跟上該線程的join函數,那麼就是順序執行,若是多個線程先完成建立和start,最後加上join函數,那麼就變成了多線程併發。
這就是今天的學習內容,其實全部知識網上都能找到,更想分享的是一種學習的方法,一種自己很不推薦的學習方法,那就是相似於探索性測試的學習,啥不懂就去看啥,有些時候,咱們學習東西確實不能非要究其內在,軟件行業的學習自己在非本行人事看來就特別神奇且枯燥,因此最初的學習,咱們須要整個圖形界面,讓咱們學到的東西有了成就感,若是上來先去研究機器碼,那麼沒幾我的願意學下去,可是無論怎樣,既然走上了軟件行業的道路,這種探索性,打破砂鍋問到底的學習,在個人感受裏應該是必經之路,也就是所謂的底層研究。以安卓開發舉例,若是作安卓開發的,雖然能寫出很漂亮的界面,解決全部的bug,若是不瞭解安卓系統linux層的知識,在個人眼裏,從未把這種研發看作大牛。固然我並不以爲不瞭解linux底層的安卓研發能夠解決任何bug
當下的軟件行業進入了一個神奇的階段,我已經聽過無數遍的理論,培訓機構出來就能賺錢,大學讀着沒用,在這裏不討論教育體制問題,從我的情感上,我以爲大學教育雖然沒有教給學生直接找工做的技能,可是給了全部學生一個可以瞭解基礎知識的園地,換而言之,做爲行業的一員,總應該有將行業發展起來的覺悟,行業內總體風氣,缺少靜下心來的沉澱。在大談敏捷,行爲驅動,機器學習的同時,本身須要靜下心來回頭看看,基礎已然不牢,再走下去是否有些危險。是否是學習軟件技術,就是爲了獲取互聯網行業那虛高的工資,是否已經侷限於第三方框架,一旦框架出現問題,只能打給客服而一籌莫展,是否有過沒有作任未嘗試就將bug歸咎於安卓系統,阿里中間件等等,是否是舊技術還沒用明白,爲了新技術就能夠再也不去研究。
仍是小菜鳥,在此大談行業發展不免有些放肆,若有不對的地方,還請各位前輩不吝指正