Python 的垃圾回收(简单总结)

大体分为4类:(根据自己的理解写的  )

1.引用计数器 2.标记清除(对1补充) 3.分代回收(对1补充) 4.缓存机制

几种回收机制的内部联系:

在Python 中维护了一个refchain的双向环状链表,这个链表中存储程序创建的所有对象,每种类型的对象中都有一个obj_refcnt引用计数器的值,引用个数+1,-1,最后当计数器变为0时就会进行垃圾回收(对象的销毁,refchain中移除)

但是,在Python中对那些可以有多个元素组成的对象可能会存在循环引用的问题,为了解决这个问题,又引出了标记清除和分代回收机制,在内部会维护4个链表和refchain  一共5个表。

在源码内部当达到各自的阈值时,就会触发扫描链表进行标记清除的动作(有循环则各自-1)但是,源码内部在上述的流程中提出了优化机制。

引用计数器具体工作流程:

在python运行时,会把程序的各种变量 对象加载到内存中,内部会根据对象的数据类型的不同找到对应得结构体(没有具体展开,了解原理即可)根据结构体的字段来创建相应的数据,放到refchain双向链表中。

Python 的垃圾回收(简单总结)_第1张图片

python 运行时会根据对象引用的次数    来分配不同对象的引用计数器的值 (如过他是一个对象那么他的初始计数器值为1)

注意:a .b 只是两个变量名  真正的对象是列表【1,2】

如上面             [1,2]  首先是一个对象        那么他的计数器的值就是 1

                                 接下来被引用啦       那么他的计数器的值就是 2

根据上面的图 可以清楚的看出列表被引用了两次

Python 的垃圾回收(简单总结)_第2张图片

b的引用发生变化,原列表的引用减少1   引用计数器变为1    

Python 的垃圾回收(简单总结)_第3张图片

 a的引用变成啦 str     原列表没有引用啦   引用计数器-1=0     此时原列表在内存被删除。

在程序结束的时候所有的对象都会被清除。

引用计数器出现的问题:

        循环引用&交叉感染:

Python 的垃圾回收(简单总结)_第4张图片

循环引用       此时 两个俩表a b  都被对方引用   导致两个表的引用计数器都为2      单纯的del a  

Python 的垃圾回收(简单总结)_第5张图片

可以看出  在内存中删除 a 对应的这个列表是删除不掉的

只有把b也删除掉 才能把他删除掉  

Python 的垃圾回收(简单总结)_第6张图片

因此就需要标记清除和分代回收的方法    来解决这个问题

(他们两都是来补充引用计数器  不过工作方式不同)

标记清除:

在python内部再创建一个链表,链表中专门存放那些可能存在循环引用的对象,再某个条件下会扫描整个表(什么时候触发这个条件没查到),如果发现有循环引用 ,就把双方的引用计数器-1      如果是0就进行回收  。

分代回收:

在内部将可能存在循环引用的对象维护成3个链表:

比如0代: 0代中的对象个数达到700个时扫描  

       1代:0代扫描10次   1代扫描1次

       2代:1代扫描10次   2代扫描1次

最后一个是python缓存     (不太了解)

 

 

你可能感兴趣的:(python,开发语言,后端)