這篇文章給大家分享的是Python中GC的垃圾回收算法的使用,相信大部分人都還沒學會這個技能,為了讓大家學會,給大家總結了以下內容,話不多說,一起往下看吧。
一、引用計數
剛開始學習Python的時候總是會有人告訴你,萬物皆對象是一大特色。在Python中每一個對象的核心就是一個結構體PyObject,它的內部有一個引用計數器(ob_refcnt)。
// object.h
struct _object {
Py_ssize_t ob_refcnt; # 引用計數值
struct PyTypeObject *ob_type;
} PyObject;
引用計數的意思就是,一個對象在它剛被New出來呱呱(gugu不是guagua)墜地的時候因為被New方法引用了所以他的引用計數就是1,如果它被引用(也就是在之前的基礎上 例如:b=a,被丟入函數列表等等被引用就會在引用計數上加1),如果引用它的對象被刪除的時候(在之前的基礎上DEL b)那么它的引用計數就會減少一一直到當它的引用計數變為0的時候,垃圾回收機制就會找上門做掉它(回收),腦補一下 :開門我是查水表的。
優點:高效,易于實現,實時性。一旦沒有引用,內存就直接釋放了。處理回收內存的時間分攤到了平時,對象有確定的生命周期。
缺點:維護性高,雖然簡單實時,但是額外占用了一部分資源,雖然邏輯簡單,但是比較麻煩。另外它還有不能解決的情況:--->循環引用,如下所示:
a=[1,2]
b=[2,3]
a.append(b)
b.append(a)
DEL a
DEL b
二、標記-清除算法
標記-清除就是用來解決循環引用的問題的只有容器對象才會出現引用循環,比如列表、字典、類、元組。 首先,為了追蹤容器對象,需要每個容器對象維護兩個額外的指針, 用來將容器對象組成一個鏈表,指針分別指向前后兩個容器對象,方便插入和刪除操作。試想一下,現在有兩種情況:
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
在標記-清除算法中,有兩個集中營,一個是root鏈表,另外一個是unreachable鏈表。對于情景A,原來再未執行DEL語句的時候,a,b的引用計數都為2,但是在DEL執行完以后,a,b引用次數互相減1。a,b陷入循環引用的圈子中,然后標記-清除算法開始出來做事,找到其中一端a,開始拆這個a,b的引用環,去掉以后發現,a,b循環引用變為了0,所以a,b就被處理到unreachable鏈表中直接被做掉。
對于情景B,簡單一看那b取環后引用計數還為1,但是a取環,就為0了。這個時候a已經進入unreachable鏈表中,已經被判為死刑了,但是這個時候,root鏈表中有b。如果a被做掉,那世界上還有什么正義... ,在root鏈表中的b會被進行引用檢測引用了a,如果a被做掉了,那么b就...涼涼,一審完事,二審a無罪,所以被拉到了root鏈表中。
三、分代回收算法
了解分類回收,首先要了解一下,GC的閾值,所謂閾值就是一個臨界點的值。隨著你的程序運行,Python解釋器保持對新創建的對象,以及因為引用計數為零而被釋放掉的對象的追蹤。從理論上說,創建==釋放數量應該是這樣子。但是如果存在循環引用的話,肯定是創建>釋放數量,當創建數與釋放數量的差值達到規定的閾值的時候,分代回收機制就開始起作用了。
垃圾回收=垃圾檢測+釋放。Python將所有的對象分為0,1,2三代;所有的新建對象都是0代對象;當某一代對象經歷過垃圾回收,依然存活,就被歸入下一代對象。Python在創建對象之前,會創建一個鏈表,零代鏈表,只不過這個鏈表是空的。每當你創建一個對象,Python便會將其加入到零代鏈表。
關于Python中GC的垃圾回收算法的使用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。