GIL (Global Interpreter Lock) 全局解釋鎖
參考資料
每一個interpreter進程,只能同時僅有一個線程來執(zhí)行, 獲得相關(guān)的鎖, 存取相關(guān)的資源.
那么很容易就會發(fā)現(xiàn),如果一個interpreter進程只能有一個線程來執(zhí)行, 多線程的并發(fā)則成為不可能, 即使這幾個線程之間不存在資源的競爭.
- 并不是Python的特性喇澡,它是在實現(xiàn)Python解析器(CPython)時所引入的一個概念
- 一個防止多線程并發(fā)執(zhí)行機器碼的一個Mutex
- 設(shè)計初衷是屯蹦,解決線程間數(shù)據(jù)一致性和狀態(tài)同步的困難
改進:為了讓各個線程能夠平均利用CPU時間屎媳,python會計算當(dāng)前已執(zhí)行的微代碼數(shù)量,達到一定閾值后就強制釋放GIL甥捺。
而這時也會觸發(fā)一次操作系統(tǒng)的線程調(diào)度(當(dāng)然是否真正進行上下文切換由操作系統(tǒng)自主決定)。
問題: (前提單進程)
[單核多線程ok镀层,處理io密集型和文件密集型不錯]這種模式在只有一個CPU核心的情況下毫無問題镰禾。任何一個線程被喚起時都能成功獲得到GIL
(因為只有釋放了GIL才會引發(fā)線程調(diào)度)。
[多核單進程不好]但當(dāng)CPU有多個核心的時候唱逢,大部分情況下主線程已經(jīng)又再一次獲取到GIL了吴侦。這個時候被喚醒執(zhí)行的線程只能白白的浪費CPU時間,
看著另一個線程拿著GIL歡快的執(zhí)行著坞古。然后達到切換時間后進入待調(diào)度狀態(tài)备韧,再被喚醒,再等待痪枫,以此往復(fù)惡性循環(huán)织堂。
總結(jié):Python的多線程在多核CPU上,只對于IO密集型計算產(chǎn)生正面效果奶陈;而當(dāng)有至少有一個CPU密集型線程存在易阳,那么多線程效率會由于GIL而大幅下降。
2.1 引用計數(shù)RC(reference count) [解決垃圾回收]
-> 垃圾回收GC(garbage collection)
為了解決內(nèi)存泄露問題吃粒,采用了對象引用計數(shù)潦俺,并基于引用計數(shù)實現(xiàn)自動垃圾回收。
優(yōu)點:
雖然引用計數(shù)必須在每次分配和釋放內(nèi)存的時候加入管理引用計數(shù)的動作,然而與其他主流的垃圾收集技術(shù)相比黑竞,
引用計數(shù)有一個最大的有點捕发,即“實時性”,任何內(nèi)存很魂,一旦沒有指向它的引用扎酷,就會立即被回收。
而其他的垃圾收集計數(shù)必須在某種特殊條件下(比如內(nèi)存分配失敹舸摇)才能進行無效內(nèi)存的回收法挨。
缺點
循環(huán)引用問題
解決方案:“標(biāo)記-清除”,“分代回收”兩種收集技術(shù)幅聘。
參考文檔
2.1 標(biāo)記-清除 [解決循環(huán)引用]
可以包含其他對象引用的容器對象(比如:list凡纳,set,dict帝蒿,class荐糜,instance)都可能產(chǎn)生循環(huán)引用。
容器+可變變量
原理:并不改動真實的引用計數(shù)葛超,而是將集合中對象的引用計數(shù)復(fù)制一份副本暴氏,在副本上標(biāo)記清除。
對于副本做任何的改動绣张,都不會影響到對象生命走起的維護答渔。
計數(shù)副本的唯一作用是尋找root object集合(該集合中的對象是不能被回收的,根對象集合)侥涵。
當(dāng)成功尋找到root object集合之后沼撕,首先將現(xiàn)在的內(nèi)存鏈表一分為二,一條鏈表中維護root object集合芜飘,
成為root鏈表<不被清除的>务豺,而另外一條鏈表中維護剩下的對象,成為unreachable鏈表燃箭。
處理: 現(xiàn)在的unreachable可能存在被root鏈表中的對象冲呢,直接或間接引用的對象,
這些對象是不能被回收的招狸,一旦在標(biāo)記的過程中敬拓,發(fā)現(xiàn)這樣的對象,就將其從unreachable鏈表中移到root鏈表中裙戏;
當(dāng)完成標(biāo)記后乘凸,unreachable鏈表中剩下的所有對象就是名副其實的垃圾對象了,
接下來的垃圾回收只需限制在unreachable鏈表中即可累榜。
2.2 分代回收 [解決垃圾回收营勤,加快回收]
存活時間劃分為不同的集合灵嫌,"代"
背景: 當(dāng)需要回收的內(nèi)存塊越多時,垃圾檢測帶來的額外操作就越多葛作,而垃圾回收帶來的額外操作就越少寿羞。
為了提高垃圾收集的效率,采用“空間換時間的策略”赂蠢。
原理:將系統(tǒng)中的所有內(nèi)存塊根據(jù)其存活時間劃分為不同的集合绪穆,每一個集合就成為一個“代”,
垃圾收集的頻率隨著“代”的存活時間的增大而減小虱岂。也就是說玖院,活得越長的對象,就越不可能是垃圾第岖,
就應(yīng)該減少對它的垃圾收集頻率难菌。
那么如何來衡量這個存活時間:通常是利用幾次垃圾收集動作來衡量,如果一個對象經(jīng)過的垃圾收集次數(shù)越多蔑滓,
可以得出:該對象存活時間就越長郊酒。0代,1代