這篇文章給大家分享的是Python中GC的垃圾回收算法的使用,相信大部分人都還沒學(xué)會這個技能,為了讓大家學(xué)會,給大家總結(jié)了以下內(nèi)容,話不多說,一起往下看吧。
一、引用計數(shù)
剛開始學(xué)習(xí)Python的時候總是會有人告訴你,萬物皆對象是一大特色。在Python中每一個對象的核心就是一個結(jié)構(gòu)體PyObject,它的內(nèi)部有一個引用計數(shù)器(ob_refcnt)。
// object.h
struct _object {
Py_ssize_t ob_refcnt; # 引用計數(shù)值
struct PyTypeObject *ob_type;
} PyObject;
引用計數(shù)的意思就是,一個對象在它剛被New出來呱呱(gugu不是guagua)墜地的時候因為被New方法引用了所以他的引用計數(shù)就是1,如果它被引用(也就是在之前的基礎(chǔ)上 例如:b=a,被丟入函數(shù)列表等等被引用就會在引用計數(shù)上加1),如果引用它的對象被刪除的時候(在之前的基礎(chǔ)上DEL b)那么它的引用計數(shù)就會減少一一直到當(dāng)它的引用計數(shù)變?yōu)?的時候,垃圾回收機(jī)制就會找上門做掉它(回收),腦補一下 :開門我是查水表的。
優(yōu)點:高效,易于實現(xiàn),實時性。一旦沒有引用,內(nèi)存就直接釋放了。處理回收內(nèi)存的時間分?jǐn)偟搅似綍r,對象有確定的生命周期。
缺點:維護(hù)性高,雖然簡單實時,但是額外占用了一部分資源,雖然邏輯簡單,但是比較麻煩。另外它還有不能解決的情況:--->循環(huán)引用,如下所示:
a=[1,2]
b=[2,3]
a.append(b)
b.append(a)
DEL a
DEL b
二、標(biāo)記-清除算法
標(biāo)記-清除就是用來解決循環(huán)引用的問題的只有容器對象才會出現(xiàn)引用循環(huán),比如列表、字典、類、元組。 首先,為了追蹤容器對象,需要每個容器對象維護(hù)兩個額外的指針, 用來將容器對象組成一個鏈表,指針分別指向前后兩個容器對象,方便插入和刪除操作。試想一下,現(xiàn)在有兩種情況:
A:
a=[1,3]
b=[2,4]
a.append(b)
b.append(a)
del a
del b
B:
a=[1,3]
b=[2,4]
a.append(b)
b.append(a)
del a
在標(biāo)記-清除算法中,有兩個集中營,一個是root鏈表,另外一個是unreachable鏈表。對于情景A,原來再未執(zhí)行DEL語句的時候,a,b的引用計數(shù)都為2,但是在DEL執(zhí)行完以后,a,b引用次數(shù)互相減1。a,b陷入循環(huán)引用的圈子中,然后標(biāo)記-清除算法開始出來做事,找到其中一端a,開始拆這個a,b的引用環(huán),去掉以后發(fā)現(xiàn),a,b循環(huán)引用變?yōu)榱?,所以a,b就被處理到unreachable鏈表中直接被做掉。
對于情景B,簡單一看那b取環(huán)后引用計數(shù)還為1,但是a取環(huán),就為0了。這個時候a已經(jīng)進(jìn)入unreachable鏈表中,已經(jīng)被判為死刑了,但是這個時候,root鏈表中有b。如果a被做掉,那世界上還有什么正義... ,在root鏈表中的b會被進(jìn)行引用檢測引用了a,如果a被做掉了,那么b就...涼涼,一審?fù)晔?,二審a無罪,所以被拉到了root鏈表中。
三、分代回收算法
了解分類回收,首先要了解一下,GC的閾值,所謂閾值就是一個臨界點的值。隨著你的程序運行,Python解釋器保持對新創(chuàng)建的對象,以及因為引用計數(shù)為零而被釋放掉的對象的追蹤。從理論上說,創(chuàng)建==釋放數(shù)量應(yīng)該是這樣子。但是如果存在循環(huán)引用的話,肯定是創(chuàng)建>釋放數(shù)量,當(dāng)創(chuàng)建數(shù)與釋放數(shù)量的差值達(dá)到規(guī)定的閾值的時候,分代回收機(jī)制就開始起作用了。
垃圾回收=垃圾檢測+釋放。Python將所有的對象分為0,1,2三代;所有的新建對象都是0代對象;當(dāng)某一代對象經(jīng)歷過垃圾回收,依然存活,就被歸入下一代對象。Python在創(chuàng)建對象之前,會創(chuàng)建一個鏈表,零代鏈表,只不過這個鏈表是空的。每當(dāng)你創(chuàng)建一個對象,Python便會將其加入到零代鏈表。
關(guān)于Python中GC的垃圾回收算法的使用就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。