0. 背景
之前介绍了Python垃圾回收的简介和内存模型,这里会对前几篇提到的回收机制进行代码剖析。注意这里用到的术语,如有疑问移步(一)简介查看。
1. 标记清除中的GC
Python使用引用计数来管理对象的生命周期。但是问题来了,如何解决循环引用的问题?
循环引用计数也好办,使用标记清除(Mark-and-Sweep)就可以解决。
标记清除方法遵循垃圾检测和垃圾回收两个阶段,其简要工程如下:
1). 寻找根集(root object set
),所谓的根集即是一些全局引用和函数栈中的引用。这些引用所用的对象时不可被删除的,而这个根集也是垃圾检测动作的起点。
2). 从根集出发,沿着根集中的每一个引用,如果能到达某个对象A,则称A为可达对象,可达对象时不可被删除的。这个阶段就是垃圾检测的阶段。
3). 当垃圾检测阶段结束后,所有的对象分可达对(reachable object
)象和不可达对象(unreachable object
)两部分,所有的可达对象都必须予以保留,而所有的不可达对象所占用的内存将被回收,这就是垃圾回收阶段。
但是使用标记清除需要明确几个问题:
a). 如何确定根集(root object set
)?
这个问题我们会在系列四-回收流程中详述。
b). 标记清除是释放那些不可达对象的内存,而这些不可达对象是通过可达对象在全集(universal set
)中的补集确定的,那全集又如何确定?
这个问题我们会在下一节详述。
c). 由于标记清除回收算法是一个深度搜索遍历的一个过程,那这个回收过程会花费很长时间吗?
答案是不会的,因为绝大部分的对象已经通过引用计数回收掉了。所有没有被引用计数回收而进入Mark-and-Sweep
环节的对象,基本都是循环引用的对象。
2. 全集(Universal Set)
a). 全集的数据结构应该是什么?
会不会是数组?