GC作为一个编程语言的自动内存管理机制,无非就是做俩件事:找到内存中不需要的对象,清除对象把内存空间空出来。一般谈起GC一般大家想起的是Java,但是Python也有,Python中采用的事引用计数为主,标记清除和分代回收为辅。
引用计数:
Python里面万物皆对象,如果一个对象被另一个对象引用,那么它的ob_ref计数就加一,引用失效的时候减一,当计数为0的时候,该对象立即被回收。但是这也存在一个问题,就是如果对象被循环引用了,使用这个方法就会导致无法自动GC,从而内存泄露。
标记清除:
标记清除分为俩个阶段,一个是标记阶段,此时GC会对所有的“活动对象”打上标记,第二阶段是把没有标记的“非活动对象”进行回收。但是对象之间存在引用,我怎么区分活动非活动对象呢?
对象之间通过引用连在一起,构成一个有向图,从根对象出发,沿着有向边遍历对象,可达的对象标记为活动对象,比如从小黑点出发,1,2,3可达,4,5不可达,1,2,3会被标记,4,5被GC回收。根对象是全局变量,调用栈,寄存器,该算法主要处理一些容器对象,比如list,dict,tuple,instance等,因为字符串和数值对象不可能造成循环引用问题,而Python也会使用一个双向链表把这些容器对象组织起来。
分代回收:
该操作方式则和Java类似,把内存根据对象的存活时间分为不同的集合,分为年轻代,中年代,老年代,也是对应了三个链表。
新创建的对象会分配在年轻代,当年轻代链表总数达到上限时,此时会触发一次GC,把可以回收的对象回收,不能回收的对象放在中年代中,以此类推,老年代中的对象时存活时间最久的对象。
而且,分代回收是建立在标记清除的基础上,因此同样也是处理容器对象。、
参考: