垃圾回收 - 引用计数法

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,一经查实,立即删除!

相关文章

目标检测YOLO实战应用案例100讲-基于RFID与目标检测的种鹅个体产蛋信息监测系统研究(续)

目录 3.4.3 结果分析 基于ROI的目标计数与产蛋信息获取 4.1 引言 4.2 ROI区域划定

【题解】JZOJ6645 / 洛谷P4090 [USACO17DEC] Greedy Gift Takers P

洛谷 P4090 [USACO17DEC] Greedy Gift Takers P 题意 n n n 头牛排成一列,队头的奶牛 i i i 拿一个礼物并插到从后往前数 c i c_i ci​ 头牛的前面,重复无限次,问多少奶牛没有礼物。 题解 发现若一头牛无法获得礼物,那么它后…

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…

加快 MySQL 数据迁移

目录 一、先导 1. 自建目标实例 2. 配置目标主从 二、源导出 1. 生成查询用户权限的SQL语句 2. 生成权限的SQL语句 3. 生成创建非主键索引的SQL语句 4. 导出源库结构 5. 导出源库数据 三、目标导入 1. 目标实例设置 2. 创建用户与权限 3. 处理结构导出文件 4. 导…

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…

1921. 消灭怪物的最大数量

原题地址 解法一 排序贪心即可。思想为先计算出每一个怪兽到达城市的时间,然后排序,有小到大进行消灭,此时的下标可视作时间。当怪兽到达城市的时间超过或等于当前时间时,即已经到达了城市,游戏失败,下标…

PVE 8 出现CPU 100% 冻结(卡死)

最近在研究PVE,然后下载官方最新版本系统8.x安装好后出现卡死问题,就连开个软件CPU也能飙到100%,开始我以为是硬件问题可能是资源不够,但是将系统切换回裸机(不用PVE启动)一点问题也没有,后来逐…

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室内场景识别数据集&#…

【Python常用函数】一文让你彻底掌握Python中的numpy.clip函数

大数据时代的到来,使得很多工作都需要进行数据挖掘,从而发现更多有利的规律,或规避风险,或发现商业价值。而大数据分析的基础是学好编程语言。本文和你一起来探索Python中的clip函数,让你以最短的时间明白这个函数的原理。也可以利用碎片化的时间巩固这个函数,让你在处理…

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

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

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

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

nsq中diskqueue详解 - 第三篇

前面一篇博客 nsq中diskqueue详解 - 第二篇_YZF_Kevin的博客-CSDN博客 我们讲了diskqueue的两种文件存储格式,diskqueue的启动入口,元数据文件的读取和写入,如果你还没了解过,强烈建议先看一下 这篇博客,我们重点讲dis…