不同于C/C++,像Python这样的语言是不需要程序员写代码来管理内存的,它的GC(Garbage Collection)机制 实现了自动内存管理。GC做的事情就是解放程序员的双手,找出内存中不用的资源并释放这块内存。 下面我们来看看Python的GC是怎么做的:
Python自带的解释器CPython主要使用了三种垃圾回收机制(引用计数为主,标记-清除和分代回收为辅):
引用计数
标记清除
分代回收
下面让我们分别了解下这几种机制:
引用计数
引用计数法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等)。
原理是:通过根节点对象(不会被删除的对象)对有向图把所有活动对象打上标记,然后回收没有被标记的非活动对象。
分代回收
原文来自:https://www.py.cn
暂无评论内容