Python的垃圾回收机制

我们在了解Python的垃圾回收机制之前,首先应该想什么是垃圾回收机制?

垃圾回收顾名思义,就是把不要不用的东西当做垃圾回收了。例如平时我们回收的是生活垃圾,那在Python里它又回收什么呢?

Python中当然回收的不是我们生活的垃圾,而是回收内存。我们都知道计算机是从内存中读取数据,那么在我们写代码的时候,例如创建一个对象,就是在计算机中开辟内存空间。而随着我们开辟的内存越来越多,计算机的负荷也越来越重,这个时候我们就需要把不用的内存给清理了,总而减轻电脑的负担。

我们在写Python代码的时候并不需要手动去清理内存,是因为Python也有自己的一套垃圾回收机制。

我们从三个方面来了解Python垃圾回收机制。

一、引用计数
python的垃圾回收采用的是引用计数机制为主和分代回收机制为辅的结合机制,当对象的引用计数变为0时,对象将被销毁,除了解释器默认创建的对象外。(默认对象的引用计数永远不会变成0)

1.对象被创建
a = 23

这里23这个对象并没有在内存中创建,因为在Python启动解释器的时候会创建一个小整数池,-5~256之间的这些对象会被自动创建加载到内存中。a = 23是为23这个整数对象增加了一个引用。

import sys
a = 88
sys.getrefcount(a)
结果:5

这是因为88这个整数目前有5个引用。

2.对象被引用
import sys
a = 88
b = a
print(sys.getrefcount(a))
print(sys.getrefcount(b))
结果:6,6

这是说明每一次赋值都会增加数据操作的引用次数,变量a,b指向的是数据88,而不是变量本身。

3.对象被作为参数,传入到一个函数中
import sys
a = 88
b = a
c = b
print(sys.getrefcount(b))
print(sys.getrefcount(c))
结果:7,7

以上赋值数据增加到了3个,sys.getrefcount(b)也增加了一个引用。

但是为什么只增加了一个,这是因为执行函数后,作为参数的引用会自动销毁,所以print(sys.getrefcount(b))在执行完成后就被删除了。

总结:当一个对象有新的引用时,它的计数器就会增加。每当引用它的对象被删除,它的引用计数就会减一,而计数器为零的时,该对象的生命就结束了。

二、标记清除
“标记-清除”算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

a=[1,2]#假设此时a的引用为1
b=[3,4]#假设此时b的引用为1
#循环引用
a.append(b)#b的引用+1=2
b.append(a)//a的引用+1=2
 
假如现在需要删除a,应该如何回收呢?
 
c=[5,6]#假设此时c的引用为1
d=[7,8]#假设此时d的引用为1
#循环引用
c.append(d)#c的引用+1=2
d.append(c)#d的引用+1=2
 
假如现在需要同时删除c、d,应该如何回收呢?
首先我们已经知道了,上面两种情况哪一个都不能用计数来完成回收,因为删除一个变量,它的引用只会-1、变成1、或者大于0、不会回收,为了解决这个问题,标记清除就来了。

puthon标记删除时通过l两个容器来完成的:死亡容器、存活容器。

首先,我们先来分析情况2,删除c、d 删除后,c的引用为1,d的引用为1,根据引用计数,还无法删除

标记删除第一步:对执行删除操作后的每个引用-1,此时c的引用为0,d的引用为0,把他们都放到死亡容器内。把那些引用仍然大于0的放到存活容器内。

标记删除第二步:遍历存活容器,查看是否有的存活容器引用了死亡容器内的对象,如果有就把该对象(注意是对象,比如0x001,不是对象的引用)从死亡容器内取出,放到存活容器内。 由于c、d都没有对象引用他们了,所以经过这一步骤,他们还是在死亡组。

标记删除第三部:将死亡组所有对象删除。 这样就完成了对从c、d的删除。 

同理我们分析出a的删除过程

标记删除第一步:对执行删除(-1)后的每个引用-1,那么a的引用就是0,b的引用为1,将a放到死亡容器,将b放到存活容器。

标记删除第二步:循环存活容器,发现b引用a,复活a:将a放到存活容器内。

标记删除第三步:删除死亡容器内的所有对象。 

三、分代收集
经过上面的两种清理方法,已经可以保证对垃圾的回收了,但还有一个问题,标记-清理什么时候执行比较好呢,是对所有对象都同时执行吗?

同时执行很显然不合理,为了更合理的进行标记-删除,就需要对对象进行分代处理。

1、新创建的对象做为0代

2、每执行一个标记-删除,存活的对象代数就+1

3、存活越持久的对象,进行标记-删除的时间间隔就越长。这个间隔称为阀值。

总结:显然分代回收就是为了解决上面两种清理方式什么时候使用,分代回收的作用就是辅助计数了
————————————————
版权声明:本文为CSDN博主「阿甘道夫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_51113819/article/details/121584478

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值