垃圾回收机制

在学习这个抽象概念前,老习惯,灵魂二问

什么是?为什么要有?

引言:在程序运行到变量定义时,会在内存空间中存放变量值,然而内存空间是有限的,变量是无限的。

Q:如何在有限的内存里存里存放无限的变量呢?

A:不存在的,但是可以对变量赋值的过程进行优化。

由此诞生了垃圾回收机制

1.什么是垃圾回收机制

垃圾回收机制(简称GC)是python解释器自带的一种机制,专门用来回收不可能访问的变量值所占用的内存空间。

Q:那么什么是垃圾呢?

A:可以用一段代码来解释:

a = 10
#这个过程在我们看来是我们给了a这个变量传了一个值为10
#而在计算机底层是这样的,在定义变量a时,在内存里开辟了一个空间,这个空间用来存放10,变量a和值10存在绑定关系,这种绑定关系叫做引用计数,此时10的引用计数为1。
a = 20
#这个时候我们重新在内存里开辟了一个空间,在里面存放了一个值为20,并将a和10的绑定关系解除,把20和a绑定。这个时候10的引用计数为0,20的引用计数为1,这样在内存里存在了一个无法访问的变量值,但是它会一直占用内存空间,这就是垃圾。

2.为什么要有垃圾回收机制

在程序的运行中,会占用大量的内存空间,时间长了就会存在许多没有用的垃圾占用大量的内存空间,如果不及时清理会造成内存使用殆尽(内存溢出),导致程序崩溃。

3.垃圾回收机制扩展

这时候可能会觉得哪里不对劲,引用计数的变化是在每一个变量定义时都会记录,存在非常大的效率问题。就像你在写作业,一个人写一次老师就检查一次,一个人还好,如果全校每个人的作业写完都是这个老师检查过去,就非常麻烦。

而且,引用计数还存在一个非常致命的缺陷,就是循环引用

# 如下我们定义了两个列表,简称列表1与列表2,变量名l1指向列表1,变量名l2指向列表2
l1=['xxx'] # 列表1被引用一次,列表1的引用计数变为1
l2=['yyy'] # 列表2被引用一次,列表2的引用计数变为1
l1.append(l2) # 把列表2追加到l1中作为第二个元素,列表2的引用计数变为2
l2.append(l1) # 把列表1追加到l2中作为第二个元素,列表1的引用计数变为2 # l1与l2之间有相互引用
# l1 = ['xxx'的内存地址,列表2的内存地址]
# l2 = ['yyy'的内存地址,列表1的内存地址]
l1 ['xxx', ['yyy', [...]]]
l2 ['yyy', ['xxx', [...]]]
l1[1][1][0]
>>>'xxx'
#到这里我们的准备工作结束了,我们可以看一下两个列表的引用计数,l1列表的内容,被l1引用了1次,被l2中第二个元素引用了一次,此时l1列表的内容引用计数为2
del l1# 列表l1的引用计数减少1,现在引用计数为1
del l2# 列表l2的引用计数减少1,现在引用计数为1
#但是此时我们却无法访问l1列表内的内容,本该被当做垃圾删除,但是他的引用计数为1,被l2列表间接引用。这个时候引用计数在这种垃圾身上就失效了。

4.标记清除

标记清除是为了弥补引用计数的缺陷,解决容器对象(list,set,dict...)内循环引用的问题。

在了解这个之前,我们可以更深入的看一下变量定义的过程

x = 10

是在栈区中有变量名x,还有x和10的关联关系,在堆区里存放着值10

当我们执行x=y时,内存中栈区和堆区的变化:

Q:标记清除是和引用计数一起工作的吗?又是怎么工作的呢?

A:标记清除是当内存即将被应用程序占满时,会把整个程序停下来,开始执行标记清除,此时分为两步:

第一步:标记

​ 标记的过程其实就是,遍历所有的GC Roots对象(栈区中的所有内容或者线程都可以作为GC Roots对象),然后将所有GC Roots的对象可以直接或间接访问到的对象标记为存活的对象,其余的均为非存活对象,应该被清除。

第二步:

​ 清除 清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。

这里再回到刚刚标记清除里的代码,循环引用时的情况,我们del l1和del l2时会在栈区里把l1和堆区内的l1的内容的元素清除绑定关系,这个时候只有在堆区内两个列表的元素在互相引用,此时就被标记了。然后所有类似的没有和栈区内的变量名有直接引用关系的都会被清除!

5.分代回收

标记清除解决了引用计数在循环引用上的缺陷,而分代回收就是为了解决引用计数的第二个缺陷,效率问题。

分代:可以做个比喻,在一个班里有40个学生,每天教一份作业,每次都检查就会很麻烦,所以我们可以在多次检查后,把这40个学生分为几部分:

第一部分:好学生,每次都交,就一周检查一次把

第二部分:良好的学生,偶尔不交,就三天检查一次把

第三部分:差生,总是不交,每次都得检查

在这样区分后,每次检查作业的效率就提高了。在程序中,每一部分就分为每一代,根据每一代的性质不同,对他们的扫描频率就不同。

即便这样,也存在缺陷,比如一个学生刚当上好学生,他就不交作业了,但是我们一周才能查出来。在程序中就是一个被放入最高代的变量,他刚进去变量绑定关系就解除了,但是这一代的扫描频率很低,很久才能把它查出来。

day05 垃圾回收机制(超小白讲解)的更多相关文章

  1. 通俗易懂.NET GC垃圾回收机制(适用于小白面试,大牛勿喷)

    情景:你接到xx公司面试邀请,你怀着激动忐忑的心坐在对方公司会议室,想着等会的技术面试.技术总监此时走来,与你简单交谈后.... 技术:你对GC垃圾回收机制了解的怎么样? 你:还行,有简单了解过. 技 ...

  2. 超详细的node/v8/js垃圾回收机制

    前言 垃圾回收器是一把十足的双刃剑.其好处是可以大幅简化程序的内存管理代码,因为内存管理无需程序员来操作,由此也减少了(但没有根除)长时间运转的程序的内存泄漏.对于某些程序员来说,它甚至能够提升代码的 ...

  3. Python垃圾回收机制--完美讲解!

    转自: http://www.jianshu.com/p/1e375fb40506 先来个概述,第二部分的画述才是厉害的. Garbage collection(GC) 现在的高级语言如java,c# ...

  4. 通过实例详细讲解PHP垃圾回收机制

    PHP垃圾回收机制:1. PHP可以自动进行内存管理,清除不需要的对象,主要使用了引用计数2. 在zval结构体中定义了ref_count和is_ref , ref_count是引用计数 ,标识此zv ...

  5. day05基本运算符,格式化输出,垃圾回收机制

    内容大纲:1.垃圾回收机制详解(了解) 引用计数 标记清除 分代回收 2.与用户交互 接收用户输入 # python3中 input # python2.7(了解) input raw_input 格 ...

  6. Java Garbage Collection基础详解------Java 垃圾回收机制技术详解

    最近还是在找工作,在面试某移动互联网公司之前认为自己对Java的GC机制已经相当了解,其他面试官问的时候也不存在问题,直到那天该公司一个做搜索的面试官问了我GC的问题,具体就是:老年代使用的是哪中垃圾 ...

  7. 成为Java GC专家(3)—如何优化Java垃圾回收机制

    为什么需要优化GC 或者说的更确切一些,对于基于Java的服务,是否有必要优化GC?应该说,对于所有的基于Java的服务,并不总是需要进行GC优化,但前提是所运行的基于Java的系统,包含了如下参数或 ...

  8. CMS垃圾回收机制

    详解CMS垃圾回收机制   原创不易,未经允许,不得转载~~~ 什么是CMS? Concurrent Mark Sweep. 看名字就知道,CMS是一款并发.使用标记-清除算法的gc. CMS是针对老 ...

  9. 要想学好Java编程,构造器、方法重载、this关键字、垃圾回收机制,这4关一定要过!

    有人说,你应该关注时事.财经,甚至流行的电影.电视剧,才有可能趁着热点写出爆文:有人说,你别再写“无聊”的技术文了,因为程序员的圈子真的很小,即便是像鸿洋那样的招牌大牛,文章是那么的干货,浏览量有多少 ...

随机推荐

  1. @Component、@Service、@Controller、@Rrepository说明

    自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: https://www.cnblogs.com/bclshuai/p/11380657.html 1       Spring容 ...

  2. 问题解决:psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

    错误提示: psql: could not connect to server: No such file or directory Is the server running locally and ...

  3. MySQL 性能优化细节

    服务器层面优化(了解) 将数据保存在内存中,保证从内存读取数据 设置足够大的innodb_buffer_pool_size,将数据读取到内存中. 建议innodb_buffer_pool_size设置 ...

  4. MAC地址表、ARP缓存表、路由表及交换机、路由器基本原理

    在网上找到了这篇讲述MAC地址,ARP协议和路由表的文章,如获至宝.一篇文章把组网中的相关概念讲的明明白白. 原文是发布在51cto博客上,但不知道为什么点进去却是404.让我没想到的是这个技术论坛上 ...

  5. 12.实战交付一套dubbo微服务到k8s集群(5)之交付dubbo-monitor到K8S集群

    dubbo-monitor官方源码地址:https://github.com/Jeromefromcn/dubbo-monitor 1.下载dubbo-monitor源码并解压 [root@hdss7 ...

  6. 1.二进制部署kubernetes

    目录 kubernetes的五个组件 master节点的三个组件 kube-apiserver kube-controller-manager kube-scheduler node节点的两个组件 k ...

  7. Python3使用cookielib模块

    同时使用过python2和python3的应该都知道,好多模块在python2中能直接安装,但是到了python3中却无法安装直接使用,同样python3中的好些模块在python2中也是一样 如下: ...

  8. Centos 7使用systemctl补全服务名称

    使用jsw将程序打包成服务后,发现不能使用service + 服务名前几个字母 + tab 快捷键补全服务名,但是tab键可以补全文件夹名,翻阅了各个文档后,最终还是找到了问题所在. 本人安装的是Ce ...

  9. 黎活明8天快速掌握android视频教程--20_采用ContentProvider对外共享数据

    1.内容提供者是让当前的app的数据可以让其他应用访问,其他应该可以通过内容提供者访问当前app的数据库 contentProvider的主要目的是提供一个开发的接口,让其他的应该能够访问当前应用的数 ...

  10. disruptor架构三 使用场景 使用WorkHandler和BatchEventProcessor辅助创建消费者

    在helloWorld的实例中,我们创建Disruptor实例,然后调用getRingBuffer方法去获取RingBuffer,其实在很多时候,我们可以直接使用RingBuffer,以及其他的API ...