溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python中垃圾回收機(jī)制的示例分析

發(fā)布時(shí)間:2021-08-17 11:58:31 來源:億速云 閱讀:144 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Python中垃圾回收機(jī)制的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

引用計(jì)數(shù)

在Python源碼中,每一個(gè)對(duì)象都是一個(gè)結(jié)構(gòu)體表示,都有一個(gè)計(jì)數(shù)字段。

typedef struct_object {
  int ob_refcnt;
  struct_typeobject *ob_type;
} PyObject;

PyObject是每個(gè)對(duì)象必有的內(nèi)容,其中ob_refcnt就是作為引用計(jì)數(shù)。當(dāng)一個(gè)對(duì)象有了新的引用時(shí),它的ob_refcnt就會(huì)增加,引用它的對(duì)象被刪除時(shí)則減少。一旦對(duì)象的引用計(jì)數(shù)為0,該對(duì)象立即被回收,占用空間就會(huì)被釋放。

優(yōu)點(diǎn)

  • 簡(jiǎn)單易用

  • 實(shí)時(shí)性好,一旦沒有引用就會(huì)被立即釋放

缺點(diǎn)

  • 需要額外空間去維護(hù)引用計(jì)數(shù)

  • 不能解決對(duì)象的循環(huán)引用

對(duì)象的循環(huán)引用
循環(huán)引用是指兩個(gè)對(duì)象相互引用且沒有外部變量引用其中任何一個(gè),導(dǎo)致引用鏈形成一個(gè)環(huán)。

>>> a = {}    # 對(duì)象a的引用計(jì)數(shù)為1
>>> b = {}    # 對(duì)象b的引用計(jì)數(shù)為1
>>> a['b'] = b  # b的引用計(jì)數(shù)增加1
>>> b['a'] = a  # a的引用計(jì)數(shù)增加1
>>> del a     # a的引用計(jì)數(shù)減少1,最后a的引用為1
>>> del b     # b的引用計(jì)數(shù)減少1,最后b的引用為1

在執(zhí)行完del操作之后,沒有任何引用指向a、b對(duì)象,但是由于這兩個(gè)對(duì)象各自包含一個(gè)對(duì)對(duì)方的引用,所以引用計(jì)數(shù)始終保持在1。

按照引用計(jì)數(shù)中內(nèi)存回收的原理,由于a和b的計(jì)數(shù)不為0,所以在使用引用計(jì)數(shù)法進(jìn)行內(nèi)存管理的時(shí)候這兩個(gè)對(duì)象不會(huì)被回收,它們會(huì)一直駐留在內(nèi)存中,造成內(nèi)存泄露。

標(biāo)記清除

標(biāo)記清除機(jī)制主要用于解決循環(huán)引用問題。

標(biāo)記清除算法是一種基于追蹤回收(tracing GC)技術(shù)實(shí)現(xiàn)的垃圾回收算法。主要分為兩個(gè)階段:

  • 標(biāo)記階段,GC會(huì)將所有的活動(dòng)對(duì)象打上標(biāo)記

  • 對(duì)那些沒有打上標(biāo)記的非活動(dòng)對(duì)象進(jìn)行回收

區(qū)分活動(dòng)對(duì)象與非活動(dòng)對(duì)象

對(duì)象之間通過引用即指針連接在一起,構(gòu)成一個(gè)有向圖,對(duì)象就是這個(gè)有向圖的節(jié)點(diǎn),而引用關(guān)系構(gòu)成這個(gè)有向圖的邊。從根對(duì)象(root object)出發(fā),沿著有向邊遍歷對(duì)象,可達(dá)的對(duì)象會(huì)被標(biāo)記為活動(dòng)對(duì)象,不可達(dá)的對(duì)象就是要被清除的非活動(dòng)對(duì)象。

根對(duì)象一般是全局變量、調(diào)用棧、寄存器等。

適用范圍

標(biāo)記清除算法作為Python輔助的垃圾收集技術(shù),主要處理的是容器對(duì)象,因?yàn)閷?duì)于字符串、數(shù)值對(duì)象等,不可能造成循環(huán)引用的問題,Python會(huì)使用一個(gè)雙向鏈表將這些容器對(duì)象組織起來。

對(duì)于標(biāo)記清除算法來說,有一個(gè)比較明顯的缺點(diǎn):為了清除非活動(dòng)對(duì)象,需要掃描整個(gè)堆內(nèi)存,哪怕只剩下小部分活動(dòng)對(duì)象也需要掃描所有對(duì)象。

分代回收

分代回收是一種以空間換時(shí)間的操作方式,建立在標(biāo)記清除技術(shù)的基礎(chǔ)之上,也是Python輔助的垃圾收集技術(shù),主要用于處理容器對(duì)象。

Python會(huì)將內(nèi)存根據(jù)對(duì)象的存活時(shí)間劃分為不同的集合,每個(gè)集合稱為一個(gè)代,主要會(huì)被分為3代:年輕代。中年代和老年代,它們會(huì)對(duì)應(yīng)3個(gè)鏈表,對(duì)應(yīng)的垃圾收集頻率隨著對(duì)象存活時(shí)間的增大而減小。

新創(chuàng)建的對(duì)象都會(huì)被分配在年輕代,當(dāng)年輕代鏈表總數(shù)達(dá)到上限時(shí),會(huì)觸發(fā)Python的垃圾回收機(jī)制,對(duì)可回收對(duì)象進(jìn)行回收,而那些不可回收的對(duì)象會(huì)被移到中年代去。依此類推,老年代對(duì)象是存活時(shí)間最久的對(duì)象,甚至有可能存活在整個(gè)系統(tǒng)的生命周期內(nèi)。

感謝各位的閱讀!關(guān)于“Python中垃圾回收機(jī)制的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI