python-垃圾回收機(jī)制


這兩天和朋友討論問題,期間提到了垃圾回收機(jī)制,我立馬想到了 python 的垃圾回收機(jī)制翩剪,之前有看過相關(guān)的資料,但是還是覺得理解不深刻彩郊,所以又去找了相關(guān)資料肢专。


垃圾回收機(jī)制

python 和 java 一樣,采用了垃圾回收機(jī)制焦辅,而像 c/c++ 這種語言是沒有采用垃圾回收機(jī)制的,因此當(dāng)一個(gè)對(duì)象再也不用時(shí)椿胯,程序員必須自己釋放內(nèi)存筷登。但采用了垃圾回收機(jī)制的語言--如 python,程序員只管創(chuàng)建和使用哩盲,不管釋放和回收前方。


python 的垃圾回收機(jī)制

當(dāng)前的垃圾回收算法多種多樣,python 采用的是引用計(jì)數(shù)為主廉油,標(biāo)記清除和分代回收為輔的垃圾回收機(jī)制惠险。
這是由多種原因決定的,有興趣的自行搜索一些資料抒线。


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

原理:當(dāng)創(chuàng)建或賦值對(duì)象的引用時(shí)班巩,對(duì)象的引用計(jì)數(shù)加1;當(dāng)銷毀對(duì)象的引用時(shí)嘶炭,對(duì)象的引用計(jì)數(shù)減1抱慌;當(dāng)對(duì)象的引用計(jì)數(shù)值為0時(shí),則說明對(duì)象已經(jīng)沒有被引用了眨猎,可以將對(duì)象所占用的內(nèi)存釋放抑进。

導(dǎo)致引用計(jì)數(shù) +1 的情況:

  1. 對(duì)象被創(chuàng)建;
  2. 對(duì)象被引用睡陪;
  3. 對(duì)象作為參數(shù)傳入函數(shù)中寺渗;
  4. 對(duì)象作為元素存儲(chǔ)在容器中。

導(dǎo)致引用計(jì)數(shù) -1 的情況:

  1. 對(duì)象被銷毀兰迫;
  2. 對(duì)象的引用指向了新的對(duì)象信殊;
  3. 對(duì)象離開了它的作用域;
  4. 對(duì)象所在的容器被銷毀汁果。

引用計(jì)數(shù)的優(yōu)點(diǎn):

  1. 無需掛起程序鸡号;(相對(duì)于標(biāo)記清除法)
  2. 引用局部性比較好;
  3. 廢棄及回收须鼎。

引用計(jì)數(shù)的缺點(diǎn):

  1. 更新引用計(jì)數(shù)值的花銷鲸伴;
  2. 引用計(jì)數(shù)占據(jù)額外的空間府蔗;
  3. 無法處理環(huán)形引用的情況。

環(huán)形引用的產(chǎn)生

什么是環(huán)形引用汞窗?比如姓赤, A 對(duì)象里引用了 B 對(duì)象,B 對(duì)象引用了 A 對(duì)象仲吏,這樣就形成了環(huán)形引用不铆。

class A:
    pass

a = A()  # 這里 a 的引用是 1 次
b = A()  # 這里同上

a.t = b  # 這里 b 的引用 +1 ,因?yàn)?b 的引用為 2 次
b.t = a  # 這里同上

del b  # 這里 b 的引用 -1裹唆,因?yàn)樵瓉?b 的引用是 2誓斥,-1 之后是1,a 的引用仍然為 2
del a  # 這里同上

# 現(xiàn)在 a许帐,b 已經(jīng)被刪了劳坑,但之前它們指向的對(duì)象的引用計(jì)數(shù)值仍為 1,不為 0成畦,
# 因此引用計(jì)數(shù)算法仍然認(rèn)為這兩個(gè)對(duì)象不是垃圾對(duì)象距芬,這就是循環(huán)引用帶來的問題。

python 為了解決循環(huán)引用的問題循帐,引入了標(biāo)記清除和分代回收框仔。


標(biāo)記清除

標(biāo)記清除也是著名的垃圾回收算法之一,最典型的就是 java 采用了這個(gè)算法拄养。
原理:

  1. 標(biāo)記階段:對(duì)所有存活對(duì)象進(jìn)行一次全局遍歷來進(jìn)行對(duì)象的標(biāo)記离斩,所有可達(dá)對(duì)象標(biāo)記為可達(dá),其它不可達(dá)的對(duì)象就是可以被回收的垃圾對(duì)象瘪匿。
  2. 清除階段:清除所有垃圾對(duì)象捐腿。

標(biāo)記清除的優(yōu)點(diǎn):

  1. 沒有環(huán)形引用的問題(相對(duì)與引用計(jì)數(shù));
  2. 無需操作引用計(jì)數(shù)值的開銷(相對(duì)與引用計(jì)數(shù))柿顶。

標(biāo)記清除的缺點(diǎn):

  1. 垃圾回收進(jìn)行時(shí)茄袖,程序必須暫停。
  2. 標(biāo)記階段的花銷較大
  3. 清除對(duì)象后會(huì)造成內(nèi)存碎片的問題(解決方法是采用標(biāo)記縮進(jìn)算法嘁锯,這里不再詳述)

在 python 中宪祥,標(biāo)記清除主要是為了解決循環(huán)引用的問題。
python 會(huì)用鏈表連接可能產(chǎn)生循環(huán)引用的對(duì)象(如 list家乘,dict蝗羊,class 等容器類,int仁锯,string這類不會(huì)產(chǎn)生循環(huán)引用)耀找,如局骤,a=[],b=[],c={},將會(huì)產(chǎn)生:head <----> a <----> b <----> c 雙向鏈表饭寺。然后從這些鏈表里的元素出發(fā)氮昧,標(biāo)記每個(gè)可到達(dá)的對(duì)象娶桦,然后那些沒有被標(biāo)記的對(duì)象將會(huì)被清除。

流程:

  1. 尋找根集合狞悲,如上面的鏈表撮抓,里面的元素一般為全局引用或函數(shù)棧上的引用
  2. 從根出發(fā),可到達(dá)對(duì)象會(huì)被標(biāo)記
  3. 清除所有沒有被標(biāo)記的對(duì)象

分代回收

分代回收在我看來摇锋,是為了提高垃圾回收效率和程序性能的的機(jī)制丹拯。它作用的地方并不是垃圾回收的內(nèi)容,而是垃圾回收這個(gè)動(dòng)作荸恕。

分代收集的思想就是活的越久的對(duì)象乖酬,就越不是垃圾,回收的頻率就應(yīng)該越低
--《Python垃圾回收機(jī)制及gc模塊詳解》

這個(gè)分代回收非常重要的原因是:一部分對(duì)象的生存周期比較短融求,一部分對(duì)象的生存周期很長(zhǎng)咬像,甚至?xí)掷m(xù)到程序結(jié)束。
這樣的話双肤,采用標(biāo)記清除時(shí),如果都一視同仁的話钮惠,會(huì)有效率的問題茅糜。

比如說,在某個(gè)對(duì)象的集合中素挽,標(biāo)記清除對(duì)象是 1s 進(jìn)行一次蔑赘,在進(jìn)行了 10 次(共10s)的標(biāo)記清除后,它發(fā)現(xiàn)一部分對(duì)象存在了 10 次预明,因此它把這部分對(duì)象移入另一個(gè)對(duì)象的集合中缩赛,對(duì)這些對(duì)象進(jìn)行 10s 一次的標(biāo)記清除,這樣的話會(huì)比之前不區(qū)分的時(shí)候效率高撰糠,占用的資源少酥馍。

python 的分代回收分三個(gè)代。(三個(gè)代其實(shí)是三個(gè)鏈表)
當(dāng)各個(gè)代中的對(duì)象數(shù)量達(dá)到閾值的時(shí)候就會(huì)觸發(fā) python 的垃圾回收阅酪。(具體可用 gc 模塊的 get_threshold() 查看)
python 首先從第三代開始檢查旨袒,如果三代中的對(duì)象大于閾值則同時(shí)回收三個(gè)代的對(duì)象,如果二代的的對(duì)象大于閾值术辐, 則回收二代和一代的對(duì)象砚尽。


如有錯(cuò)誤,麻煩評(píng)論告知辉词,無比感激必孤!


參考

http://www.jb51.net/article/52229.htm
http://www.cnblogs.com/Xjng/p/5128269.html
https://my.oschina.net/hnuweiwei/blog/291367?p=1
http://blog.csdn.net/yueguanghaidao/article/details/11274737

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瑞躺,隨后出現(xiàn)的幾起案子敷搪,更是在濱河造成了極大的恐慌兴想,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件购啄,死亡現(xiàn)場(chǎng)離奇詭異襟企,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狮含,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門顽悼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人几迄,你說我怎么就攤上這事蔚龙。” “怎么了映胁?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵木羹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我解孙,道長(zhǎng)坑填,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任弛姜,我火速辦了婚禮脐瑰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘廷臼。我一直安慰自己苍在,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布荠商。 她就那樣靜靜地躺著寂恬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪莱没。 梳的紋絲不亂的頭發(fā)上初肉,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音饰躲,去河邊找鬼朴译。 笑死,一個(gè)胖子當(dāng)著我的面吹牛属铁,可吹牛的內(nèi)容都是我干的眠寿。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼焦蘑,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼盯拱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤狡逢,失蹤者是張志新(化名)和其女友劉穎宁舰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奢浑,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蛮艰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雀彼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壤蚜。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖徊哑,靈堂內(nèi)的尸體忽然破棺而出袜刷,到底是詐尸還是另有隱情,我是刑警寧澤莺丑,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布著蟹,位于F島的核電站,受9級(jí)特大地震影響梢莽,放射性物質(zhì)發(fā)生泄漏萧豆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一昏名、第九天 我趴在偏房一處隱蔽的房頂上張望涮雷。 院中可真熱鬧,春花似錦葡粒、人聲如沸份殿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至颂斜,卻和暖如春夫壁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沃疮。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工盒让, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人司蔬。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓邑茄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親俊啼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肺缕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 雖然是自己轉(zhuǎn)載的但是是真的好的一篇圖文并茂的對(duì)垃圾回收機(jī)制的講解!!! 先來個(gè)概述,第二部分的畫述才是厲害的。 G...
    東皇Amrzs閱讀 118,582評(píng)論 13 176
  • 現(xiàn)在的高級(jí)語言如java同木,c#等浮梢,都采用了垃圾收集機(jī)制,而不再是c彤路,c++里用戶自己管理維護(hù)內(nèi)存的方式秕硝。但是這種方...
    LittlePy閱讀 731評(píng)論 0 1
  • python 中的垃圾回收機(jī)制 Python的GC模塊主要運(yùn)用了“引用計(jì)數(shù)”(reference counting...
    機(jī)械師的呆子閱讀 485評(píng)論 0 0
  • python里回收機(jī)制是以引用計(jì)數(shù)為主,標(biāo)記-清除和分代收集兩種機(jī)制為輔洲尊。經(jīng)過查看相應(yīng)的資料發(fā)現(xiàn)如下1.pytho...
    夏樹的寶馬閱讀 350評(píng)論 0 1
  • Y來自云南颊郎,在富士康工作憋飞,結(jié)識(shí)了現(xiàn)在的丈夫,倆人步入婚姻的殿堂姆吭,沒有理由榛做,彼此 相愛。但她老公來自河北内狸,兩個(gè)人的時(shí)...
    左岸花開2020閱讀 520評(píng)論 0 3