python垃圾回收机制上

原创
2012/05/14 21:40
阅读数 1W
    现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患。     
    对于一个字符串、列表、类甚至数值都是对象,且定位简单易用的语言,自然不会让用户去处理如何分配回收内存的问题。
    python里也同java一样采用了垃圾收集机制,不过不一样的是,python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略。
    引用计数机制:
    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))

引用计数为0时,该对象生命就结束了。
    引用计数机制的优点:
         1、简单
        2、实时性:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处:处理回收内存的时间分摊到了平时。        
    引用计数机制的缺点:
        1、维护引用计数消耗资源
        2、循环引用
list1 = []
list2 = []
list1.append(list2)
list2.append(list1)

    list1与list2相互引用,如果不存在其他对象对它们的引用,list1与list2的引用计数也仍然为1,所占用的内存永远无法被回收,这将是致命的。
    对于如今的强大硬件,缺点1尚可接受,但是循环引用导致内存泄露,注定python还将引入新的回收机制。

展开阅读全文
打赏
2
8 收藏
分享
加载中
和楼主私下讨论循环引用,如果在引用计数下的垃圾回收机制而引发的内存泄露问题,颇有感慨。期待楼主的下篇。
2012/05/28 23:43
回复
举报

引用来自“河边洗澡”的评论

引用来自“西昆仑”的评论

引用来自“河边洗澡”的评论

引用来自“西昆仑”的评论

向楼主提几个问题:
1. 楼主认为Python的实时释放(即引用计数为0时直接释放)有很多优点,但是JAVA为什么不怎么做?是不是有她的考虑?当系统中存在大量的垃圾时,集中处理会不会效率更好一点?
2. Java中定期或者在某个环境的出发下导致垃圾回收,会考虑的一个问题是内存碎片,所以会进行对象在内存中的移动,并更新相关地址信息。Python的垃圾回收释放也有类似的考虑?

1、一方面狭义上讲,很多高级语言不认为引用计数是回收机制。另一方面,引用计数可以避免改变对象在内存中的位置,Python是用c实现的,这样可以更方便的利用C/C++扩展或者交互。另外python也有高级的回收机制,后面再说。
2、python的内存机制不太清楚,只知道大量采用了内存池,它的垃圾回收只是在一个对象没有必要存在的情况下释放而已。

1. 为啥引用技术不算回收机制?
2. 引用技术可以避免改变对象在内存中的位置? 啥意思。我想到JAVA在垃圾回收的时候有时会移动对象避免内存碎片。PYTHON中是要避免这种情况的吗?

1、因为引用计数无法解决循环引用
2、引用计数为0,直接释放内存,不会去移动其他。因为使用了大量内存池(单单整数就分为小整数的内存池跟大整数的内存池),所以内存碎片也比较小了吧。

楼主的这两个回答让我豁然开朗~
2012/05/16 19:56
回复
举报
河边洗澡博主

引用来自“西昆仑”的评论

引用来自“河边洗澡”的评论

引用来自“西昆仑”的评论

向楼主提几个问题:
1. 楼主认为Python的实时释放(即引用计数为0时直接释放)有很多优点,但是JAVA为什么不怎么做?是不是有她的考虑?当系统中存在大量的垃圾时,集中处理会不会效率更好一点?
2. Java中定期或者在某个环境的出发下导致垃圾回收,会考虑的一个问题是内存碎片,所以会进行对象在内存中的移动,并更新相关地址信息。Python的垃圾回收释放也有类似的考虑?

1、一方面狭义上讲,很多高级语言不认为引用计数是回收机制。另一方面,引用计数可以避免改变对象在内存中的位置,Python是用c实现的,这样可以更方便的利用C/C++扩展或者交互。另外python也有高级的回收机制,后面再说。
2、python的内存机制不太清楚,只知道大量采用了内存池,它的垃圾回收只是在一个对象没有必要存在的情况下释放而已。

1. 为啥引用技术不算回收机制?
2. 引用技术可以避免改变对象在内存中的位置? 啥意思。我想到JAVA在垃圾回收的时候有时会移动对象避免内存碎片。PYTHON中是要避免这种情况的吗?

1、因为引用计数无法解决循环引用
2、引用计数为0,直接释放内存,不会去移动其他。因为使用了大量内存池(单单整数就分为小整数的内存池跟大整数的内存池),所以内存碎片也比较小了吧。
2012/05/16 19:55
回复
举报

引用来自“河边洗澡”的评论

引用来自“西昆仑”的评论

向楼主提几个问题:
1. 楼主认为Python的实时释放(即引用计数为0时直接释放)有很多优点,但是JAVA为什么不怎么做?是不是有她的考虑?当系统中存在大量的垃圾时,集中处理会不会效率更好一点?
2. Java中定期或者在某个环境的出发下导致垃圾回收,会考虑的一个问题是内存碎片,所以会进行对象在内存中的移动,并更新相关地址信息。Python的垃圾回收释放也有类似的考虑?

1、一方面狭义上讲,很多高级语言不认为引用计数是回收机制。另一方面,引用计数可以避免改变对象在内存中的位置,Python是用c实现的,这样可以更方便的利用C/C++扩展或者交互。另外python也有高级的回收机制,后面再说。
2、python的内存机制不太清楚,只知道大量采用了内存池,它的垃圾回收只是在一个对象没有必要存在的情况下释放而已。

1. 为啥引用技术不算回收机制?
2. 引用技术可以避免改变对象在内存中的位置? 啥意思。我想到JAVA在垃圾回收的时候有时会移动对象避免内存碎片。PYTHON中是要避免这种情况的吗?
2012/05/16 19:44
回复
举报
河边洗澡博主

引用来自“西昆仑”的评论

向楼主提几个问题:
1. 楼主认为Python的实时释放(即引用计数为0时直接释放)有很多优点,但是JAVA为什么不怎么做?是不是有她的考虑?当系统中存在大量的垃圾时,集中处理会不会效率更好一点?
2. Java中定期或者在某个环境的出发下导致垃圾回收,会考虑的一个问题是内存碎片,所以会进行对象在内存中的移动,并更新相关地址信息。Python的垃圾回收释放也有类似的考虑?

1、一方面狭义上讲,很多高级语言不认为引用计数是回收机制。另一方面,引用计数可以避免改变对象在内存中的位置,Python是用c实现的,这样可以更方便的利用C/C++扩展或者交互。另外python也有高级的回收机制,后面再说。
2、python的内存机制不太清楚,只知道大量采用了内存池,它的垃圾回收只是在一个对象没有必要存在的情况下释放而已。
2012/05/16 19:41
回复
举报
向楼主提几个问题:
1. 楼主认为Python的实时释放(即引用计数为0时直接释放)有很多优点,但是JAVA为什么不怎么做?是不是有她的考虑?当系统中存在大量的垃圾时,集中处理会不会效率更好一点?
2. Java中定期或者在某个环境的出发下导致垃圾回收,会考虑的一个问题是内存碎片,所以会进行对象在内存中的移动,并更新相关地址信息。Python的垃圾回收释放也有类似的考虑?
2012/05/15 21:23
回复
举报
更多评论
打赏
6 评论
8 收藏
2
分享
返回顶部
顶部