文档章节

python垃圾回收机制上

河边洗澡
 河边洗澡
发布于 2012/05/14 21:40
字数 525
阅读 2284
收藏 5
    现在的高级语言如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还将引入新的回收机制。

© 著作权归作者所有

下一篇: 回车换行
河边洗澡

河边洗澡

粉丝 22
博文 17
码字总数 13057
作品 0
浦东
私信 提问
加载中

评论(6)

太阳落雨
和楼主私下讨论循环引用,如果在引用计数下的垃圾回收机制而引发的内存泄露问题,颇有感慨。期待楼主的下篇。
西昆仑
西昆仑

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

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

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

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

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

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

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

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

楼主的这两个回答让我豁然开朗~
河边洗澡
河边洗澡 博主

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

注:这篇文章基于我在布达佩斯的RuPy大会上所作的演讲。我觉得与其直接将幻灯片发布出来,不如在我还有印象的时候将它写成博客来的更有意义。同 样,我会在将来发布RuPy大会的视频链接。我计...

oschina
2014/06/19
5K
28
python是如何进行内存管理的

Python引入了一个机制:引用计数。 python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要...

糖宝lsh
2018/12/14
47
0
史上最全的Python面向对象知识点疏理

面向对象技术简介 类: 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 类变量:类变量在整个实例化的对象中是公用的。类变量定义...

乐乎无趣
2017/11/03
30
0
Python 核心编程 (全)

浅拷贝和深拷贝 1.浅拷贝:是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容。相当于把变量里面指向的一个地址给了另一个变量就是浅拷贝,而没有创建一个新的对象,如a=b...

代码打碟手
2018/08/18
18
1
(转)Python 面试中可能会被问到的30个问题

本次面试面了10几家,拿了3家offer, 总结下本次面试题汇总,送给有需要的人! 作者:KotlinPython 原标题:10 家公司 Python 面试题总结 来源:https://mp.weixin.qq.com/s/CaFybiK3fDG19Z...

实验楼
2018/08/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
702
10
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
39
0
spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
今天
25
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
74
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
73
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部