乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      簡單理解python的垃圾回收機(jī)制

       印度阿三17 2019-10-20

        前言理解python中變量的定義:抽象理解python中變量的定義過程


       1、垃圾回收機(jī)制的基本組成:

        python采用的是以引用計數(shù)為主,以分代回收和標(biāo)記清除為輔的垃圾回收機(jī)制

      2、詳細(xì)分析垃圾回收機(jī)制:

      (1)首先是引用計數(shù):

        在python中,每創(chuàng)建一個對象,那么python解釋器會自動為其設(shè)置一個特殊的變量,這個變量稱為引用計數(shù)(初始值默認(rèn)是1)。一旦有一個新變量指向這個對象,那么這個引用計數(shù)的值就會加1。如果引用計數(shù)的值為0。那么python解釋器的內(nèi)存管理系統(tǒng)就會自動回收這個對象所占的內(nèi)存空間,刪除掉這個對象。

      ①引用計數(shù) 1的情況:

      • 對象被創(chuàng)建,例如a = "laoliang"

      • 對象被引用,例如b = a

      • 對象被作為參數(shù),傳入到一個函數(shù)中,例如fun(a)

      • 對象作為一個元素,存儲在容器中,例如data_list=[a,b]

      ②引用計數(shù)-1的情況:

      • 對象的別名被顯式銷毀,例如del a

      • 對象的別名被賦予新的對象,例如a = 24

      • 一個對象離開它的作用域,例如func函數(shù)執(zhí)行完畢時,func函數(shù)中的局部變量(全局變量不會)

      • 對象所在的容器被銷毀,或從容器中刪除對象

      ③查看一個對象的引用計數(shù):

      import sys
      a = "hello laoliang"
      sys.getrefcount(a)

      注意:查看a對象的引用計數(shù)時,比正常計數(shù)大1,因為調(diào)用函數(shù)的時候傳入a,這會讓a的引用計數(shù) 1。

      (2)既然已經(jīng)有引用計數(shù)了,那么為什么還要提出分代回收呢?

      原因就是引用計數(shù)沒辦法解決“循環(huán)引用”的情況。

      ①“循環(huán)引用”分析:

      a = ["laoliang", ]   # 語句1
      b = ["laowang", ]    # 語句2
      a.append(b)          # 語句3
      b.append(a)          # 語句4
      # 此時對象的值:a = ["laoliang", b] b = ["laowang", a] del a # 語句5 del b # 語句6
      # 執(zhí)行完語句5和語句6是希望同時刪除掉a對象和b對象

      分析:

        執(zhí)行完語句1到語句4之后,會形成上圖左邊所示的對象引用關(guān)系。

        由上圖可知,在執(zhí)行“del a”語句之后,只是刪除了對象的引用,也就是此時a變量這個名字被刪除,也就是此時對象[b, "laoliang"]的引用計數(shù)減1;執(zhí)行"del b"語句也是同樣的情況。

        此時對象[b, "laoliang"]中有一個引用,指向了[a, "laowang"],所以此時[b, "laoliang"]的引用計數(shù)不為0,所以存在于內(nèi)存中,不真正被刪除。[a, "laowang"]也是一個道理。但是,此時,由于顯式指向它們的變量已經(jīng)不存在了,所以也沒辦法刪除了,就會導(dǎo)致它們一直存在于內(nèi)存空間中。 這就是循環(huán)引用出現(xiàn)的問題。 此時,單靠引用計數(shù)沒辦法解決問題。所以便提出了分代回收。

      ②分代回收:

      注意:在分代回收中,如果某對象的引用計數(shù)為0,那么它所占的內(nèi)存空間同樣也會被python解釋器回收。

      a、此時在python中每創(chuàng)建一個對象,那么就會把對象添加到一個特殊的“鏈表”中,這個鏈表稱為"零代鏈表"。每當(dāng)創(chuàng)建一個新的對象,那么就會將其添加到零代鏈表中。當(dāng)這個"零代鏈表"中的對象個數(shù)達(dá)到某一個指定的閥值的時候,python解釋器就會對這個"零代鏈表"進(jìn)行一次“掃描操作”。這個“掃描操作”所做的工作是查找鏈表中是否存在循環(huán)引用的對象,如果在掃描過程中,發(fā)現(xiàn)有互相引用的對象,那么會讓這些對象的引用計數(shù)都減少1。此時,如果某些對象引用計數(shù)變成0,那么就會被python解釋器回收其所占用的內(nèi)存空間;如果對象的引用計數(shù)仍然不為0,那么會把此時存活的對象遷移到“一代鏈表”中。

      b、同樣,python解釋器也會在一定的情況下,也掃描“一代鏈表”,判斷其中是否存在互相引用的對象。如果存在,那么同樣也是讓這些對象的引用計數(shù)都減少1。此時,如果某些對象引用計數(shù)變成0,那么就會被python解釋器回收其所占用的內(nèi)存空間;如果對象的引用計數(shù)仍然不為0,那么會把此時存活的對象遷移到“二代鏈表”中。

      c、同樣,python解釋器也會在一定的情況下,也會掃描"二代鏈表",判斷其中是否存在互相引用的對象。如果存在,那么同樣也是讓這些對象的引用計數(shù)都減少1。此時,如果某些對象引用計數(shù)變成0,那么就會被python解釋器回收其所占用的內(nèi)存空間;如果對象的引用計數(shù)仍然不為0,那么會把此時存活的對象遷移到一個新的特殊的內(nèi)存空間。此時重新進(jìn)行"零代鏈表 -> 一代鏈表 -> 二代鏈表"的循環(huán)。

      這就是python的分代回收機(jī)制。

      (3)那么既然已經(jīng)有分代回收了,那么為什么又要提出標(biāo)記-清除呢?

      原因就是分代回收沒辦法解決“誤刪”的情況。

      ①“誤刪”分析:

      a = ["laoliang", ]   # 語句1
      b = ["laowang", ]    # 語句2
      a.append(b)          # 語句3  
      b.append(a)          # 語句4  
      # 此時對象的值:a = ["laoliang", b] b = ["laowang", a]。 ["laoliang", b]、["laowang", a]的引用計數(shù)都為2 del a # 語句5
      # 此時["laoliang", b]的引用計數(shù)為1, ["laowang", a]的引用計數(shù)為2
      # 執(zhí)行完語句5只希望刪除a對象

        如果按照分代回收的方式來處理上述語句。那么,python解釋器在執(zhí)行完語句5之后。在一定的情況下進(jìn)行查找循環(huán)引用對象的時候,會發(fā)現(xiàn)此時["laowang", a]對象和["laoliang", b]對象存在互相引用的情況。所以此時就會讓這兩個對象的引用計數(shù)減1。此時,["laoliang", b]對象的引用計數(shù)為0,所以["laoliang", b]對象被真正刪除,但是其實此時["laowang", a]對象中是有一個變量引用原來的["laoliang", b]對象的。如果["laoliang", b]對象被真正刪除的話,那么此時["laowang", a]對象中的a變量就沒有用了,就沒有辦法訪問了。但是其實我們是希望它有用的,所以這個時候就出現(xiàn)“誤刪”的情況了。所以此時就需要結(jié)合“標(biāo)記-清除”來解決問題了。

      ②標(biāo)記-清除:

      • 此時同樣是檢測鏈表中的相互引用的對象,然后讓它們的引用計數(shù)減1之后;

      • 但是此時會將所有的對象分為兩組:死亡組(death_group)和存活組(survival_group),把引用計數(shù)為0的對象添加進(jìn)死亡組,其它的對象添加進(jìn)存活組;

      • 此時會對存活組的對象進(jìn)行分析,只要對象存活,那么其內(nèi)部的對象當(dāng)然也必須存活。如果發(fā)現(xiàn)內(nèi)部對象死亡,那么就會想方設(shè)法讓其活過來,通過這樣子就能保證不會刪錯對象了。

      eg:對于①的題目的重新分析:   在檢查死亡組的時候,會發(fā)現(xiàn)[a,"laowang"]對象中的a所指向的對象存在于死亡組中,所以就會想方設(shè)法讓其復(fù)活,此時就能夠保證[a, "laowang"]對象中所有的對象都是存活的。   實際運行分析:    在刪除了a對象之后,b對象中的內(nèi)部的對象都是可以訪問的。這就是因為使用了標(biāo)記-清除。     

      3、綜上所述:

        python就是采用的是以引用計數(shù)為主,以分代回收和標(biāo)記清除為輔的垃圾回收機(jī)制。三者相輔相成,共同來處理、維護(hù)python程序所占用的內(nèi)存空間。     參考資料:https://www.jianshu.com/p/6c783517a5e9https://www.cnblogs.com/saolv/p/8411993.htmlhttps://blog.csdn.net/admin_maxin/article/details/81632580https://blog.csdn.net/weixin_34232363/article/details/85943385來源:https://www./content-1-512651.html

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多