python語(yǔ)言開(kāi)發(fā)垃圾回收機(jī)制原理教程
一.什么是垃圾回收機(jī)制
垃圾回收機(jī)制(簡(jiǎn)稱(chēng)GC), 解釋器自帶的一種機(jī)制
它是一種動(dòng)態(tài)存儲(chǔ)管理技術(shù),自動(dòng)釋放不再被程序引用的對(duì)象所占用的內(nèi)存空間
二.為什么要有垃圾回收機(jī)制
程序的運(yùn)行過(guò)程中會(huì)申請(qǐng)大量的內(nèi)存空間
對(duì)于一些無(wú)用的空間如果不及時(shí)清理的話會(huì)導(dǎo)致內(nèi)存溢出(不夠用),程序就會(huì)崩潰
管理內(nèi)存是非常復(fù)雜的事情,垃圾回收機(jī)制就把程序員從復(fù)雜的內(nèi)存管理中解放出啦
三.垃圾回收機(jī)制的原理
1.引用計(jì)數(shù)
引用計(jì)數(shù)就是變量名與變量值的關(guān)聯(lián)次數(shù), 以此來(lái)跟蹤和回收垃圾
直接引用
通過(guò)變量名直接引用
x = 18 #18被引用了一次,計(jì)數(shù)為1 y = x #18被引用加1次,計(jì)數(shù)為2 z = y #18被引用加1次,計(jì)數(shù)為3 print(id(x)) #140725488808736 print(id(y)) #140725488808736 print(id(z)) #140725488808736
間接引用
容器對(duì)其的引用都是間接
x = 18 #18被引用一次,計(jì)數(shù)為1 li = [1,2,x] #通過(guò)列表引用,計(jì)數(shù)加1,為2 dic = {'age': x} #通過(guò)字典引用, 計(jì)數(shù)加1,為3 print(id(x)) #140725486514976 print(id(li[2])) #140725486514976 列表引用,計(jì)數(shù)4 print(id(dic['age'])) #140725486514976 字典引用,計(jì)數(shù)5
2.棧區(qū) / 堆區(qū)
棧區(qū) : 存放的是變量名與變量值的內(nèi)存地址映射關(guān)系
堆區(qū) : 存放的是值真正的位置
3.總結(jié)
直接引用指的是從棧區(qū)出發(fā)直接引用到的內(nèi)存地址
間接引用指的是從棧區(qū)出發(fā)引用到堆區(qū)后,再通過(guò)進(jìn)一步引用才能到達(dá)的內(nèi)存地址
四.標(biāo)記清除
1.循環(huán)引用問(wèn)題(也叫交叉引用)
#我們先定義列表 l1=[0] # 列表1被引用一次,列表1的引用計(jì)數(shù)變?yōu)? l2=[1] # 列表2被引用一次,列表2的引用計(jì)數(shù)變?yōu)? #將列表加入另一個(gè)列表 l1.append(l2) # 把列表2追加到l1中作為第二個(gè)元素,列表2的引用計(jì)數(shù)變?yōu)? l2.append(l1) # 把列表1追加到l2中作為第二個(gè)元素,列表1的引用計(jì)數(shù)變?yōu)? #解除比變量名"l1"和"l2"與值的對(duì)應(yīng)關(guān)系 del l1 del l2
2.循環(huán)引用導(dǎo)致的結(jié)果
值不再被任何名字關(guān)聯(lián),但是值的引用計(jì)數(shù)并不會(huì)為0
應(yīng)該被回收但又不能被回收
3.解決方法 : 清除-標(biāo)記
容器對(duì)象的的引用都有可能產(chǎn)生循環(huán)引用, 而清除-標(biāo)記就是為解決這個(gè)問(wèn)題的
當(dāng)應(yīng)用程序可用空間被耗盡時(shí), 清除-標(biāo)記會(huì)停止整個(gè)程序, 然后先標(biāo)記, 再清除
- 標(biāo)記
但凡是可以從棧區(qū)出發(fā),找到對(duì)應(yīng)堆區(qū)內(nèi)容的(直接或間接引用)就標(biāo)記存活,非存活則清除
具體點(diǎn):標(biāo)記的過(guò)程其實(shí)就是,遍歷所有的"GC Roots"對(duì)象(棧區(qū)中的所有內(nèi)容或者線程都可以作為"GC Roots"對(duì)象)
然后將所有"GC Roots"的對(duì)象可以直接或間接訪問(wèn)到的對(duì)象標(biāo)記為存活的對(duì)象,其余的均為非存活對(duì)象,應(yīng)該被清除 - 清除
遍歷堆中的對(duì)象,將沒(méi)有標(biāo)記存活的對(duì)象都清理掉
五.分代回收
1.效率問(wèn)題
基于引用計(jì)數(shù)的回收機(jī)制,每次回收內(nèi)存,都需要把所有對(duì)象的引用計(jì)數(shù)都遍歷一遍
這是非常消耗時(shí)間的,于是引入了分代回收來(lái)提高回收效率
分代回收采用的是用**“空間換時(shí)間”**的策略。
2.解決方法 : 分代回收
分代
分代指的是根據(jù)變量的存活時(shí)間來(lái)劃分他們的等級(jí)
一個(gè)變量經(jīng)常被引用,等級(jí)(權(quán)重)就會(huì)提高,權(quán)重達(dá)到設(shè)定值就會(huì)進(jìn)入下一個(gè)等級(jí)
當(dāng)經(jīng)過(guò)多次掃描都沒(méi)有被回收,"GC機(jī)制"就會(huì)認(rèn)為該變量是常量
于是對(duì)其的掃描頻率會(huì)降低
回收
當(dāng)計(jì)數(shù)降低,就容易被回收
分代回收可以起到提升效率的效果,但也存在一定的缺點(diǎn):
比如一個(gè)變量剛從低等級(jí)轉(zhuǎn)入高等級(jí),它就被解除了綁定關(guān)系
它應(yīng)該被回收,但高等級(jí)掃描頻率低于低等級(jí)
那么這個(gè)已被解除綁定關(guān)系的變量無(wú)法及時(shí)得到清理
總結(jié)
垃圾回收機(jī)制是在清理垃圾和釋放內(nèi)存的前提下
允許一些垃圾不被釋放為代價(jià)(就是等級(jí)權(quán)重高點(diǎn)的垃圾不會(huì)及時(shí)被清理)
以此換取引用計(jì)數(shù)掃描頻率的降低,從而提升其性能
這是一種以空間換時(shí)間的解決方案
以上就是python語(yǔ)言開(kāi)發(fā)垃圾回收機(jī)制原理教程的詳細(xì)內(nèi)容,更多關(guān)于python語(yǔ)垃圾回收機(jī)制原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于jieba.cut與jieba.lcut的區(qū)別及說(shuō)明
這篇文章主要介紹了關(guān)于jieba.cut與jieba.lcut的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05如何用python多次調(diào)用exe文件運(yùn)行不同的結(jié)果
有個(gè)C++項(xiàng)目是讀取配置參數(shù)文件并打印對(duì)應(yīng)的結(jié)果,后來(lái)需要多次修改配置文件并運(yùn)行,于是想到寫(xiě)個(gè)python腳本執(zhí)行這一過(guò)程,今天通過(guò)本文給大家分享python多次調(diào)用exe文件運(yùn)行不同的結(jié)果,感興趣的朋友一起看看吧2023-05-05利用Python實(shí)現(xiàn)Picgo圖床工具
這篇文章主要介紹了如何利用Python實(shí)現(xiàn)Picgo圖床工具,PyPicGo?是一款圖床工具,是PicGo是Python版實(shí)現(xiàn),并支持各種插件自定義插件,目前PyPicGo自帶了gitee、github、SM.MS和七牛云圖傳,以及rename、notify和typora等插件,下面來(lái)看文章內(nèi)容介紹,需要的朋友可以參考一下2021-11-11python實(shí)現(xiàn)xlwt xlrd 指定條件給excel行添加顏色
這篇文章主要介紹了python實(shí)現(xiàn)xlwt xlrd 指定條件給excel行添加顏色,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07django-rest-framework解析請(qǐng)求參數(shù)過(guò)程詳解
這篇文章主要介紹了django-rest-framework解析請(qǐng)求參數(shù)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07Python實(shí)現(xiàn)多腳本處理定時(shí)運(yùn)行
這篇文章主要介紹了Python實(shí)現(xiàn)多腳本處理定時(shí)運(yùn)行,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06Python實(shí)現(xiàn)按逗號(hào)分隔列表的方法
今天小編就為大家分享一篇Python實(shí)現(xiàn)按逗號(hào)分隔列表的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10