原创 Python中GC的垃圾回收算法分析

发布时间:2020-01-13 11:00:30 浏览 1652 来源:博学谷 作者:照照

    相信大家在面试中常常会碰到有关垃圾回收的问题,的确,Python和其他很多编程语言一样,都自带垃圾回收机制。本文主要和大家来分析一下Python中的垃圾回收算法。首先我们要知道,GC计算机术语指的是垃圾回收。而Python中的垃圾回收是以引用计数为主,但是为了弥补其算法的不足,所以又引入了标记-清除和分代收集算法为辅。

     

    Python中垃圾回收算法

     

    一、引用计数
      

    刚开始学习Python的时候总是会有人告诉你,万物皆对象是一大特色。在Python中每一个对象的核心就是一个结构体PyObject,它的内部有一个引用计数器(ob_refcnt)。
      

    // object.h
      

    struct _object {
      

    Py_ssize_t ob_refcnt; # 引用计数值
      

    struct PyTypeObject *ob_type;
      

    } PyObject;
      

    引用计数的意思就是,一个对象在它刚被New出来呱呱(gugu不是guagua)坠地的时候因为被New方法引用了所以他的引用计数就是1,如果它被引用(也就是在之前的基础上 例如:b=a,被丢入函数列表等等被引用就会在引用计数上加1),如果引用它的对象被删除的时候(在之前的基础上DEL b)那么它的引用计数就会减少一一直到当它的引用计数变为0的时候,垃圾回收机制就会找上门做掉它(回收),脑补一下 :开门我是查水表的。
      

    优点:高效,易于实现,实时性。一旦没有引用,内存就直接释放了。处理回收内存的时间分摊到了平时,对象有确定的生命周期。
      

    缺点:维护性高,虽然简单实时,但是额外占用了一部分资源,虽然逻辑简单,但是比较麻烦。另外它还有不能解决的情况:--->循环引用,如下所示:
      

    a=[1,2]
      

    b=[2,3]
      

    a.append(b)
      

    b.append(a)
      

    DEL a
      

    DEL b
      

    二、标记-清除算法
      

    标记-清除就是用来解决循环引用的问题的只有容器对象才会出现引用循环,比如列表、字典、类、元组。 首先,为了追踪容器对象,需要每个容器对象维护两个额外的指针, 用来将容器对象组成一个链表,指针分别指向前后两个容器对象,方便插入和删除操作。试想一下,现在有两种情况:
      

    A:
      

    a=[1,3]
      

    b=[2,4]
      

    a.append(b)
      

    b.append(a)
      

    del a
      

    del b

     

    B:
      

    a=[1,3]
      

    b=[2,4]
      

    a.append(b)
      

    b.append(a)
      

    del a
      

    在标记-清除算法中,有两个集中营,一个是root链表,另外一个是unreachable链表。对于情景A,原来再未执行DEL语句的时候,a,b的引用计数都为2,但是在DEL执行完以后,a,b引用次数互相减1。a,b陷入循环引用的圈子中,然后标记-清除算法开始出来做事,找到其中一端a,开始拆这个a,b的引用环,去掉以后发现,a,b循环引用变为了0,所以a,b就被处理到unreachable链表中直接被做掉。
      

    对于情景B,简单一看那b取环后引用计数还为1,但是a取环,就为0了。这个时候a已经进入unreachable链表中,已经被判为死刑了,但是这个时候,root链表中有b。如果a被做掉,那世界上还有什么正义... ,在root链表中的b会被进行引用检测引用了a,如果a被做掉了,那么b就...凉凉,一审完事,二审a无罪,所以被拉到了root链表中。

     

    三、分代回收算法
      

    了解分类回收,首先要了解一下,GC的阈值,所谓阈值就是一个临界点的值。随着你的程序运行,Python解释器保持对新创建的对象,以及因为引用计数为零而被释放掉的对象的追踪。从理论上说,创建==释放数量应该是这样子。但是如果存在循环引用的话,肯定是创建>释放数量,当创建数与释放数量的差值达到规定的阈值的时候,分代回收机制就开始起作用了。
      

    垃圾回收=垃圾检测+释放。Python将所有的对象分为0,1,2三代;所有的新建对象都是0代对象;当某一代对象经历过垃圾回收,依然存活,就被归入下一代对象。Python在创建对象之前,会创建一个链表,零代链表,只不过这个链表是空的。每当你创建一个对象,Python便会将其加入到零代链表。

     

    以上就是Python中GC的垃圾回收算法分析,大家都看懂了吗?如果对于引用计数,标记-清除和分代收集算法还有什么问题,可以上博学谷官网咨询在线老师,进行更为深入细致的学习。

    申请免费试学名额    

在职想转行提升,担心学不会?根据个人情况规划学习路线,闯关式自适应学习模式保证学习效果
讲师一对一辅导,在线答疑解惑,指导就业!

上一篇: 了解Python五大特性提高工作效率 下一篇: 分享15天学习python视频教程?隔壁的小伙伴都羡慕了

相关推荐 更多

热门文章

  • 什么是Dubbo?Dubbo在项目中是怎么用的?都支持什么协议?
  • 前端好找工作吗?现在前端还值得入行吗?
  • 全国计算机专业大学排名清单
  • 学习大数据必须掌握哪些核心技术?
  • 女生到底适不适合学编程做程序媛?
  • 北京电商运营培训班多少钱?贵吗?
  • IT行业选哪个学科职业发展空间大?
  • 入门Python基础知识点总结
  • 入行数据分析可行吗?适不适合学习?
  • 学Java开发能实现月薪12K吗?
  • 查看更多

扫描二维码,了解更多信息

博学谷二维码