在的实现里面是通过写屏障 Write实现的,其处理模型可以看做是对引用对象赋值时候的AOP 切面;一个是Pre-Write一个是Post-Write。一般是在对象赋值后使用写后屏障更新卡表;
对于高并发下面的并发修改,JDK 后新增一个参数 -XX:+ 来判断卡表是否变成脏了,如果没有变脏才更新卡表;
4.6 并发的可达性分析
主流编程语言基本都是通过可达性分析来判断对象是否存活,算法理论上需要全过程都基于一致性的快照中去分析,意味着要停止所有用户线程;上面介绍过来记录的根节点开始便利查找对象图,这个步骤的时间是和堆的内存大小成正比的,堆越大,就需要更多时间去标记;
如何保障一致性快照 。三色标记来辅助理解
如果在回收期间一切用户线程停止,扫描就不会有任何的问题,但是如果有用户线程参与的话,一种是把要回收的变成不回收的,这个没什么问题,最多下次再回收,如果把本来存活的对象标记为要回收,就会出现问题了;下面描述此过程;
正常情况:用户线程不干预
1.引用是有方向的,只有被黑色引用才能存活;(只有根节点里面引用的对象才能活,对象引用更节点对象,不代表是可以存活的对象)
2.扫描过程,灰色是正在扫描
【二JVM.垃圾回收算法/策略内存分配】3.正常完成,黑色存活,白色回收 ,非黑即白
非正常情况:用户线程干预
1.扫描时,用户线程干预,切断引用(红色),本来灰色的引用指向了已经扫描过的黑色,黑色不会二次扫描了;
2.扫描时,用户线程干预,切断的引用是一段引用链:导致两个/多个对象丢失(红色)
问题的来源:原本是黑色的由于被并发干预变成了白色;下面两个条件同时满足的时候会导致这个问题
插入了一个或者黑色对象到白色对象的引用删除了灰色对象到白色对象的引用
要解决这个问题,破坏其中一个条件就可以=> 两种解决方案:
增量更新,当黑色插入时,记录黑色节点,扫描结束后,重写扫描这些黑色节点;可以简单的理解为,一旦黑色插入白色,就把黑色转变成黑色;(CMS 使用该方案)
原始快照At theSATB: 灰色节点要删除的时候,保存灰色节点到删除节点记录,扫描结束之后,灰色节点作为根节点,重写扫描;(G1,使用该方案)
5.经典垃圾回收器
下图7种作用于不同内存区域位置的垃圾回收器,连线表示可以搭配使用;
5.1
文章插图
JDK1.3之前的新生代唯一的垃圾回收器,单线程,运行时停止所有用户线程 ; 会发生STD 体验比较差;但是也有优点,适合内存资源有限,内存消耗较小,单线程情况下没有线程交互开销;
使用场景:客户端模式;
5.2
回收器是回收器的多线程并行版本,代码也复用很多
JDK9 之前官方推荐使用的是+ CMS , 搭配很单一 ,JDK9之后还取消了+Old , + CMS; 直接并入CMS
单线程环境下效果比 还要差,只有在核心比较多的情况下,才能体现其效率;默认开启的线程是CPU 核心数;参数-XX: 限制线程个数
5.3
新生代,标记-复制算法,并行 垃圾回收器;
目标:达到一个可控制的吞吐量;表面特性类似于
吞吐量=用户代码时间/(用户代码时间+GC 时间)
-XX: 最大垃圾回收时间;设置大于0 的毫秒值,但是也不能设置的过于小,过小会频繁的GC,减低了吞吐量;
-XX: 直接设置吞吐量大小 0~100,如果设置19 就是 1/(1+19)= 5% ;系统默认时99 ,就是1/(1+99) = 1%,允许1% GC 时间
- JAVA的垃圾收集器与内存分配策略【一篇文章直接看懂】
- 二 Android——数据持久化技术 SharedPreference存储
- 二、Redis持久化
- 二 JavaWeb——Servlet入门
- 二 零基础学习WEB前端开发:HTML标签及开发工具
- 二、HashMap和WeakHashMap的区别
- 二 UI自动化进销存系统之会员管理
- 视频行为理解之二
- 架构 ThinkPHP5文档学习笔记--
- 二 Django入门