与 C/C++ 不同,像 Python 这样的语言不需要程序员编写代码来管理内存。它的GC(Garbage Collection)机制实现了自动内存管理。 GC所做的就是解放程序员的双手,找出内存中未使用的资源并释放这块内存。我们来看看Python的GC是如何工作的:
Python自带的解释器CPython主要使用了三种垃圾回收机制(引用计数为主,mark-sweep和分代回收为辅):
引用计数
标记清除
分代回收
下面让我们分别了解下这几种机制:
引用计数
引用计数方法Reference Counting的原理是每个对象都维护一个引用计数字段来记录对象被引用的次数(如果对变量->引用->对象的问题不清楚,可以查看这个文章Python的深拷贝和浅拷贝),如果有新的引用指向对象,则对象引用计数加一,当引用被销毁时,对象引用计数减一,当用户的引用计数为0 ,内存被释放。你可以查看 sys.getrefcount() 函数引用的对象数。
这种方法主要存在两种问题:
需要去维护引用计数,存在执行效率问题
无法解决循环引用问题
所谓循环引用就是:有一组引用计数不为0的对象,但是这组对象实际上并没有被变量引用,它们是相互引用的,不会有其他变量引用这组对象的对象。因此,如果使用引用计数,这些对象占用的内存将永远不会释放。
写一段代码举个例子:
In [23]: a = []
In [24]: b = []
In [25]: a.append(b)
In [26]: b.append(a)
In [27]: a
Out[27]: [[[...]]]
In [28]: b
Out[28]: [[[...]]]
可以看出a和b中都存在循环引用。这时候即使使用del语句删除变量,已经使用的内存也不会被回收,所以需要第二种GC机制:
标记清除
Mark-Sweep是针对循环引用问题的一种回收机制,作用对象为容器类型的对象(如:list、set、dict等)。
其原理是:通过根节点对象(不会被删除的对象)标记有向图上的所有活动对象,然后回收未标记的非活动对象。
分代回收
分代收集是一种基于标记和清除辅助收集容器对象的GC机制。无论正在开发的程序的类型和大小如何,都有一些共同点:内存的某些部分的生命周期较短,而其他部分的生命周期较长,可能伴随整个程序的开始和结束。所以分代收集根据内存在系统中的存活时间将它们分成不同的集合:一共三个集合,每个集合称为一个代。随着对象生命周期的增加,它们的垃圾收集频率会降低。也就是说:对象的存活时间越长,它成为垃圾的可能性就越小,它的回收频率就会降低。新创建的对象都是第一代的。当第一代的回收总数达到上限时,就会触发GC机制:可以回收的对象占用的内存会被释放,不能回收的会移到中年。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 详细讲解 Python 面向对象的编程类、示例和方法11/02
- ♥ 如何在python中调用线程01/12
- ♥ 如何在python中输入整数08/19
- ♥ python中如何使用RE正则表达式检查字符串12/29
- ♥ python repr()和str()区别总结11/16
- ♥ wb在python中有什么用11/16
内容反馈