zoukankan      html  css  js  c++  java
  • python进阶之垃圾回收

    内存使用

    程序在运行的过程需要开辟内存空间,比如创建一个对象需要一片内存空间,定义变量需要内存空间。有内存的开辟,势必也要有内存的释放,不然只进不出那不是貔貅了吗?即使有开辟有释放在短期内还是会有垃圾内存的存在。

    内存管理

    在有些语言中,内存的开辟和回收需要在代码中完成,典型的例子就是C语言。C语言中开辟一块内存:ptr=(int*)malloc(sizeof(int)*n); 释放一块内存:free(ptr);这个过程是需要写在内存使用之前的程序中的(没有轮子怎么办,咱们自己造)。而Java,Python这类语言内存的开辟和回收不需要代码实现,在后台中有专门负责内存回收的机制GC。

    python中使用的垃圾回收机制有两个:

    1.引用计数,标记清除

    2.隔代回收

    引用计数,标记清除

    python里每一个东西都是对象,它们的核心就是一个结构体:PyObject

    typedef struct_object {
        int ob_refcnt;
        struct_typeobject *ob_type;
    } PyObject;

    PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少

    #define Py_INCREF(op)   ((op)->ob_refcnt++) //增加计数
    #define Py_DECREF(op)  //减少计数
    if (--(op)->ob_refcnt != 0) 
         ; 
    else 
         __Py_Dealloc((PyObject *)(op))

    创建对象时Python立即向操作系统请求内存,同时Python将对象的C结构体里的 ob_refcnt 的值设为1。

    如果对变量a重新赋值,此时变量a就会指向一个新的对象,新对象的引用数值为1,旧对象引用计数的值就会被置成0。

    当python 的垃圾回收机制发现内存中的对象的计数引用值为0时,它就发现该自己闪亮登场了。垃圾回收机制会销毁该对象,释放内存。

    引用计数,标记清除这一招是十分奏效的,可以解决大部分的对象回收。但是就是有那么一些情况是这一招解决不了的,那就是循环引用所谓循环应用指的是两个对象互相引用,且成为了一个孤岛,没有别的对象关联。

    这种情况下,引用计数值一直都是1,想要释放 ’tommorr‘ 不行,因为它被 ’another‘引用了,所以要先释放 ’another‘才能使用 ’tommor‘,但是’another‘又被tommorr引用,也无法释放。这该怎么办呢?这时需要python垃圾回收的第二个机制 隔代回收出马了。

    隔代回收

    隔代回收机制主要3板斧:

    第一:所有创建的对象都会加入到零代链表中,并扫描零代链表中所有的循环引用。如图发现两个对象的循环引用。

      

    第二:将发现的循环引用的引用计数都减1。

    当循环引用计数值为0之后,就被标记清除,垃圾回收第一规则就生效。如果清除一次引用计数还不为0咋办呢?那就是第三步

     第三步:将零代中引用计数不为0的对象加入到一代链表中,在一代链表中会重复零代中的循环计数减1操作。同时如果生命力顽强到一代链表都没处理的,那么会加入到二代链表。

     

    以上讲到的是垃圾回收机制的大体思路,其实python的垃圾回收机制比以上描述的要复杂很多,很多深奥的东西可以看篇文章:https://www.cnblogs.com/pinganzi/p/6646742.html

  • 相关阅读:
    JDK和TOMCAT环境变量配置
    MEF(Managed Extensibility Framework )的入门介绍
    这样的数据导出你知道?
    ListBox实现拖拽排序功能
    各种技术资源汇总
    大话数据结构-排序
    大话数据结构-查找
    CheckListBox的实现方式分析
    listbox里面添加WrapPanel ,支持自适应换行
    RESTful 接口实现简明指南
  • 原文地址:https://www.cnblogs.com/goldsunshine/p/11561612.html
Copyright © 2011-2022 走看看