python和c混合编程 gil_终于搞明白python与gil
感想:東看一篇文章西看一篇文章,終于把gil的概念理順了
我們都知道,比方我有一個4核的CPU,那么這樣一來,在單位時間內(nèi)每個核只能跑一個線程,然后時間片輪轉(zhuǎn)切換。但是Python不一樣,它不管你有幾個核,單位時間多個核只能跑一個線程,然后時間片輪轉(zhuǎn)。看起來很不可思議?但是這就是GIL搞的鬼。任何Python線程執(zhí)行前,必須先獲得GIL鎖,然后,每執(zhí)行100條字節(jié)碼,解釋器就自動釋放GIL鎖,讓別的線程有機會執(zhí)行。這個GIL全局鎖實際上把所有線程的執(zhí)行代碼都給上了鎖,所以,多線程在Python中只能交替執(zhí)行,即使100個線程跑在100核CPU上,也只能用到1個核。通常我們用的解釋器是官方實現(xiàn)的CPython,要真正利用多核,除非重寫一個不帶GIL的解釋器
gil:全局解釋器鎖
存在原因:
早期設(shè)計python解釋器時是單核時代,并沒有考慮多核cpu情況
1.python的是使用引用計數(shù)的,當(dāng)變量的引用計數(shù)為0就會被垃圾回收機制回收
2.python是解釋型語言,默認的解析器cpython是將python語言翻譯成c,再調(diào)用c函數(shù)實現(xiàn)執(zhí)行python程序
3.線程與進程不同,是共享用戶地址空間的,也就是共享全局變量
綜上,如果同一個時刻有兩個線程執(zhí)行,那么全局變量的引用計數(shù)可能同時從0變成1,最終它的引用計數(shù)就是1,而卻有兩個線程在使用它,這顯然是不對的.
解釋:
全局:針對全局資源/同一個時刻,不管有多少個核,都只有一個線程能使用cpu資源
解釋鎖:cpython鎖(C語言實現(xiàn)的Python解釋器)
為什么java沒有g(shù)il鎖呢?
java實現(xiàn)了顆粒度更小的鎖,而程序的執(zhí)行順序是:獲取鎖-執(zhí)行程序-釋放鎖,所以增加了獲取和釋放鎖的資源開銷,所以全局鎖這一把大鎖其實也有好處,切換線程的資源浪費較少.
解釋器怎么切換線程?
如果是純計算的程序,沒有 I/O 操作,解釋器會每隔100次操作就釋放這把鎖,讓別的線程有機會 執(zhí)行(這個次數(shù)可以通sys.setcheckinterval來調(diào)整)同一時間只會有一個獲得GIL線程在跑,其他線程都處于等待狀態(tài)
哪種任務(wù)適合用多線程?
1、如果是CPU密集型代碼(循環(huán)、計算等),由于計算工作量多和大,計算很快就會達到100,然后觸發(fā)GIL的釋放與在競爭,多個線程來回切換損耗資源,所以在多線程遇到CPU密集型代碼時,單線程會比較快
2、如果是I\O密集型代碼(文件處理、網(wǎng)絡(luò)爬蟲),開啟多線程實際上是并發(fā)(不是并行),IO操作會進行IO等待,線程A等待時,自動切換到線程B,這樣就提升了效率
怎么優(yōu)化?
1.改用多進程,多個Python進程有各自獨立的GIL鎖
2.將計算代碼轉(zhuǎn)成c代碼,使用調(diào)用c代碼的接口,將cpu密集型任務(wù)切換成io任務(wù):對所有面向I/O的(會調(diào)用內(nèi)建的操作系統(tǒng)C代碼的)程序來說,GIL會在這個I/O調(diào)用之前被釋放,以允許其他線程在這個線程等待I/O的時候運行。我們可以把一些 計算密集型任務(wù)用C語言編寫,然后把.so鏈接庫內(nèi)容加載到Python中,因為執(zhí)行C代碼,GIL鎖會釋放
與多進程使用變量的區(qū)別:
多進程:linux系統(tǒng)里面,fork出來的進程,其變量與源進程相同,如果只做讀取,那么不會內(nèi)存分配,如果發(fā)生寫入,那么創(chuàng)建新內(nèi)存頁
缺點?
導(dǎo)致python無法實現(xiàn)真正意義上的多線程
Java吧 收集整理 java論壇 www.java8.com
總結(jié)
以上是生活随笔為你收集整理的python和c混合编程 gil_终于搞明白python与gil的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 灵图天行者9 pc版_原神PC预下载现已
- 下一篇: websocket python爬虫_p