垃圾回收 - 引用计数法

GC原本是一种“释放怎么都无法被引用的对象的机制”。那么人们自然而然就会想到,可以让所有对象事先记录下“有多少程序引用了自己”。让各对象知道自己的“人气指数”,从而让没有人气的对象自己消失,这就是引用计数法。

1、计数器

计数器表示的是对象的人气指数,也就是有多少程序引用了这个对象。计数器是无符号的整数
在这里插入图片描述
1.1计数器的增减
在GC-标记清除算法的其他算法中,没有分块时mutator会调用下面这样的函数,启动GC分配空闲的内存空间。

garbage_collect(){.....
}

然而在引用计数法中并没有mutator明确启动GC的语句,引用计数法与mutator的执行密切相关,他在mutator的处理过程中通过增减计数器的值来进行内存管理。这涉及到new_obj()函数和update_ptr()函数

1.2 new_obj()函数

new_obj(size){obj = pickup_chunk(size,$free_list)if(obj == NULL) allocation_fail()elseobj.ref_cnt = 1return obj
}

1.3 update_ptr()函数
该函数用于更新指针ptr,使其指向对象obj,同时进行计数器值的增减。

update_ptr(ptr,obj){inc_ref_cnt(obj)dec_ref_cnt(*ptr)*ptr = obj
}inc_ref_cnt(obj){obj.ref_cnt ++;
}dec_ref_cnt(obj){obj.ref_cnt --;if(obj.ref_cnt == 0)for(child : children(obj))dec_ref_cnt(*child)reclaim(obj)
}

该程序具体进行的是以下2项操作:

  • 对指针ptr新引用的对象obj的计数器进行增量操作
  • 对指针ptr之前引用的对象*ptr的计数器进行减量操作

在变更数组元素等的时候会进行指针的更新。通过更新指针,可能会产生没有被任何程序引用的的垃圾对象。引用计数法会监督在更新指针的时候是否有产生垃圾,从而在产生垃圾的时候立即将其回收。

2、优缺点

2.1优点

  • 可即刻回收垃圾
  • 最大暂停时间短
  • 没有必要沿着指针查找。

2.2缺点

  • 计数器值的增减处理繁重
  • 计数器需要占用很多位
  • 实现繁琐复杂
  • 循环引用无法回收

3、延迟引用计数法

因为引用计数法中计数器值的增减处理繁重。于是就产生了延迟引用计数法。计数器增减处理繁重的原因之一是从根的引用变化频繁,因此我们就让从根引用的指针的变换不反映在计数器上。比如我们把重写全局变量指针的update_ptr($ptr,obj)改写成*ptr = obj。
这样一来,即使频繁重写堆中对象的引用关系,对象的计数器值也不会有所变化。但是这样内存管理还是不能顺利进行。因为引用没有反应在计数器上,所以各个对象的计数器没有正确表示出对象本身被引用数。于是就有可能发生对象仍在活动但却被错当成垃圾回收的情况。
在这里插入图片描述
于是,我们在延迟引用计数法中使用ZCT(Zero Count Table),他会事先记录下计数器值在dec_ref_cnt()函数作用下变为0的对象。
在这里插入图片描述
因为计数器值为0的对象不一定都是垃圾,所以暂时先将这些对象保留。

优点:通过延迟减轻了因根引用频繁发生变化导致的计数器增减所带来的额外负担。
缺点:为了延迟计数器的增减,垃圾不能立马回收,导致垃圾压迫成堆,我们也就失去了引用计数法的优点-可即刻回收垃圾。

4、Sticky引用计数法

在引用计数法中,我们有必要研究一件事,那就是要为计数器设置多大的位宽,假设为了反映所有引用,计数器需要一个字(32位机器就是32位)的空间。但是这样回大量消耗内存空间。比如2个字的对象就要附加一个字的计数器,也就是说计数器害的对象所占空间增大了1.5倍
在这里插入图片描述
对此我们有个方法,那就是用来减少计数器位宽的“Sticky引用计数法"。举个例子,我们假设用于计数器的位数为5位,那么这种计数器最多只能数到2的5次方减1,就是31个引用数。如果此对象被大于31个引用对象引用,那么计数器就会溢出。针对计数器溢出,需要暂停堆计数器的管理,对付这种对象,我们主要有两种方法:

4.1、什么都不做
对于计数器溢出的对象,我们可以这样处理:不再增减计数器的值,就把它放着。但是这样一来,即使这个对象成了垃圾(引用次数为0)也不能将其回收,这样就白白浪费了内存空间。

4.2、使用标记清除算法处理
在适当的时候使用标记清除算法来充当引用计数法的后援。这样做的优点是在计数器溢出后即使成了垃圾,程序还是能够回收它,并且还可以回收循环的垃圾。

5、1位引用计数法

1位引用计数法是Stick的一个极端例子,就是计数器的大小只有一位,瞬间就会溢出。

6、部分标记清除法

之前已经讲过,引用计数法存在的一大问题就是不能回收循环的垃圾。这是引用计数法的一大特色,用GC标记清除算法就不会有这种问题。那么我们自然会想到,只要跟之前使用延迟引用计数法时一样,利用GC 标记清除算法不就好了吗?也就是说,可以采用一般情况下执行引用计数法,在某个时刻启动 GC 标记清除算法的方法。

6.1前提
在部分标记清除算法中,对象会被涂成4种颜色来进行管理:

颜色含义表示
绝对不是垃圾的对象(对象产生时的初始颜色)00
绝对是垃圾的颜色01
搜索完毕的对象10
阴影可能是循环垃圾的对象11

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/65825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

personalized image enhancement 调研

Personalized Image Enhancement Using Neural Spline Color Transforms 这是TIP期刊 2020年的一篇论文,首先提出了一个能预测曲线的网络,预测一些锚点,根据锚点插值出连续的曲线,然后用曲线对raw image进行retouching。然后提出了…

【强化学习】MDP马尔科夫链

基本元素 状态集:表示智能体所处所有状态的全部可能性的集合。类似的集合,行为集,回报集决策:规定我在某个状态下,我做出某个action马尔可夫链:学术上来说是无记忆性质。说白了就是我只在乎我目前的状态。…

Ansible学习笔记9

yum_repository模块: yum_repository模块用于配置yum仓库的。 测试下: [rootlocalhost ~]# ansible group1 -m yum_repository -a "namelocal descriptionlocalyum baseurlfile:///mnt/ enabledyes gpgcheckno" 192.168.17.106 | CHANGED &g…

eureka服务注册和服务发现

文章目录 问题实现以orderservice为例orderservice服务注册orderservice服务拉取 总结 问题 我们要在orderservice中根据查询到的userId来查询user,将user信息封装到查询到的order中。 一个微服务,既可以是服务提供者,又可以是服务消费者&a…

云端笔记系统-自动化测试

文章目录 1. 思维导图编写 Web 自动化测试用例2. 创建测试项目3. 根据思维导图设计【云端笔记】自动化测试用例3.1. 准备工具类3.2. 测试注册页面3.3. 测试登陆页面3.4. 测试添加博客页3.5. 测试我的博客列表页3.6. 测试修改博客页3.7. 测试博客列表页3.8. 测试博客详情页3.9. …

MATLAB中residue函数用法

目录 语法 说明 示例 求解具有实根的部分分式展开式 展开具有复数根和同次分子及分母的分式 展开分子次数高于分母次数的分式 residue函数的功能是部分分式展开(部分分式分解)。 语法 [r,p,k] residue(b,a) [b,a] residue(r,p,k) 说明 [r,p…

多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比

多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比 目录 多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | Matlab实现GRU-Adaboost和GRU多变量时间序列预测对比 模型描述 M…

Elasticsearch终端命令行用法大全

API作用使用场景curl localhost:9200/_cluster/health?pretty查看ES健康状态curl localhost:9200/_cluster/settings?pretty查看ES集群的设置其中persistent为永久设置,重启仍然有效;trainsient为临时设置,重启失效curl localhost:9200/_ca…

Java 复习笔记 - 方法篇

文章目录 一,方法的定义二,最简单的方法定义和调用三,带参数的方法定义和调用四,带返回值方法的定义和调用五,小结六,方法的重载七,方法简单练习1,数组遍历2,数组最大值3…

每日一题 2511. 最多可以摧毁的敌人城堡数目

难度:简单 翻译:寻找距离最远的 1 和 -1 的组合,要求它们之间只有0 class Solution:def captureForts(self, forts: List[int]) -> int:res, t 0, -1for i, fort in enumerate(forts):if fort -1 or fort 1:if t > 0 and fort ! f…

YOLO目标检测——室内场景识别数据集下载分享

目标检测室内场景识别数据集可以广泛应用于各种需要对室内场景进行目标识别和跟踪的领域,包括安防监控、智能家居、物流仓储管理等 数据集点击下载: YOLO室内场景识别数据集(一)5950图片26类别.rar YOLO室内场景识别数据集&#…

使用 Privoxy 在 Linux 上配置本地代理服务器详细教程

Privoxy 是一个功能强大的开源网络代理软件,它可以帮助我们在 Linux 系统上搭建本地代理服务器。通过配置和使用 Privoxy,您可以实现更安全、匿名以及自定义过滤规则等高级特性。本文将详细介绍如何在 Linux 环境下利用 Privoxy 配置并运行本地代理服务器…

【Java基础】深入理解反射、反射的应用(工厂模式、代理模式)

文章目录 1. Java反射机制是什么?1.2 Java反射例子 2. Java反射机制中获取Class的三种方式及区别?3. Java反射机制的应用场景有哪些?3.1. 优化静态工厂模式(解耦)3.1.1 优化前(工厂类和产品类耦合&#xff…

JavaScript运行机制与实践应用

一、JavsScript运行机制 1、JavaScript 是一种解释型语言,它的执行机制主要包括以下几个步骤: 2、事件循环 3、JavaScript运行模型 4、JavaScript任务 5、JavaScript宏任务和微任务 6、案例分析 console.log(script start) setTimeout(function () {co…

RocketMQ消息队列-@RocketMQMessageListener实现原理

使用Spring-RocketMQ时,只需要引入rocketmq-spring-boot-starter包,并且定义以下消费者,就可以很简单的实现消息消费 Component RocketMQMessageListener(topic "first-topic", consumerGroup "my-producer-group", s…

SEAN代码(1)

代码地址 首先定义一个trainer。 trainer Pix2PixTrainer(opt)在Pix2PixTrainer内部,首先定义Pix2PixModel模型。 self.pix2pix_model Pix2PixModel(opt)在Pix2PixModel内部定义生成器,判别器。 self.netG, self.netD, self.netE self.initialize_…

Ansible学习笔记10

1、在group1的被管理机里的mariadb里创建一个abc库; 1) 然后我们到agent主机上进行检查: 可以看到数据库已经创建成功。 再看几个其他命令: #a组主机重启mysql,并设置开机自启 ansible a -m service -a "namemy…

HDMI 输出实验

FPGA教程学习 第十四章 HDMI 输出实验 文章目录 FPGA教程学习前言实验原理实验过程程序设计时钟模块(video_pll)彩条产生模块(color_bar)配置数据查找表模块(lut_adv7511)I2C Master 寄存器配置模块(i2c_c…

elasticSearch+kibana+logstash+filebeat集群改成https认证

文章目录 一、生成相关证书二、配置elasticSearh三、配置kibana四、配置logstash五、配置filebeat六、连接https es的java api 一、生成相关证书 ps:主节点操作 切换用户:su es 进入目录:cd /home/es/elasticsearch-7.6.2 创建文件&#x…

Adobe Illustrator 2023 for mac安装教程,可用。

Adobe Illustrator 是行业标准的矢量图形应用程序,可以为印刷、网络、视频和移动设备创建logos、图标、绘图、排版和插图。数以百万计的设计师和艺术家使用Illustrator CC创作,从网页图标和产品包装到书籍插图和广告牌。此版本是2023版本,适配…