引用计数
Python默认的垃圾回收机制是“引用计数”,每个对象维护一个ob_ref字段。它的优点是机制简单。当有新的引用指向对象时,引用计数加1,当对象的引用被销毁时,引用计数减1。一旦对象的引用计数为0,对象立即被回收,并且占用的内存将被释放。它的缺点是需要额外的空间来维护引用计数,但主要问题是无法解决“循环引用”。
什么是循环引用? A 和 B 互相引用,A 和 B 都没有外部引用。虽然它们的引用计数都是 1,但显然应该被回收。例子:
a = { } # a 的引用为 1
b = { } # b 的引用为 1
a['b'] = b # b 的引用增 1,b的引用为2
b['a'] = a # a 的引用增 1,a的引用为 2
del a # a 的引用减 1,a的引用为 1
del b # b 的引用减 1, b的引用为 1
在这个例子中,del语句减少了a和b的引用计数,并删除了用于引用的变量名,但是由于这两个对象各自包含了对另一个对象的引用,所以虽然最后两个对象不能通过名称访问,但是引用计数没有减少到零。所以这个对象不会被销毁,它会一直驻留在内存中,从而造成内存泄漏。为了解决循环引用问题,Python引入了两种GC机制:mark-sweep和generational collection。
标记清除
Mark——Sweep是一种基于追踪(Tracing)回收技术的垃圾收集算法。对象通过引用(指针)链接在一起形成一个有向图,而对象又形成了这个有向图。的节点和引用关系构成了这个有向图的边。从根对象(root object)开始,沿着有向边遍历对象,可达的对象标记为有用的对象,不可达的对象为要清除的对象。所谓根对象就是在一些全局引用对象和函数栈中的引用,这些引用所引用的对象是不能删除的。
作为Python的辅助垃圾回收技术,mark-and-sweep算法主要处理一些容器对象,比如list、dict、tuple、instance等,因为不可能对string和numeric对象造成循环引用问题。 Python 使用双向链表来组织这些容器对象。
分代回收
分代回收是一种以空间换取时间的操作方式。 Python根据对象的存活时间将内存划分为不同的集合。每个集合称为一代。 Python将内存分为3个“代”,分别为年轻代。 (Generation 0)、Middle Age(Generation 1)、Old Age(Generation 2),它们分别对应三个链表,它们的垃圾回收频率随着对象存活时间的增加而降低。新创建的对象会分配到新生代。当年轻代链表总数达到上限时,会触发Python垃圾回收机制,回收那些可以回收的对象,那些不会回收的对象会被移到Go到中年,并且以此类推,老年代的对象是存活时间最长的对象,即使在整个系统的生命周期中也是如此。同时,分代回收基于标记清除技术。
分代收集也将这些容器对象作为 Python 的辅助垃圾收集技术来处理。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ python如何查看错误类型是什么?10/31
- ♥ Python中的$是什么意思?09/05
- ♥ 用python2或python3学习python11/13
- ♥ 如何解决python的导入错误10/06
- ♥ python异常中的语句处理11/14
- ♥ 如何使用 python tkinter label 标签?10/09
内容反馈