当前位置: 首页 > 知识库问答 >
问题:

java - Java AQS的cancelAcquire方法中的 node.next = node; 利于gc?

姚自强
2023-05-19

看Java AQS源码的时候看到cancelAcquire方法中有这么一句:

node.next = node; // help GC

想问一下为什么这样做就有助于gc。

自己想了很多点感觉都不对。比如如果是为了回收,但是AQS中回收canceled node也不是在这个方法中删除的,其他方法比如acquireQueued就删除了所有canceled node。

共有1个答案

孟花蜂
2023-05-19

问题的评论区已经给出答案了。

建议直接去看原文章,写得很好,不过我这里也稍微总结一下。

那篇文章大概意思是,虽然没有这个操作node.next = node;我们也能移除这个节点,但是如果这个节点先进入old gen,那么即使它被移除,不可达了,在minor gc时依旧不会清理该节点,且由于该节点存在对young gen的引用,会导致在它之后的节点,如果被移除队列了,依旧无法回收,因为虽然它之后的节点在young gen中,但这个节点被old gen中的一个对象引用着,垃圾回收器并不能回收它,即 跨代引用问题

久而久之会导致堆积大量已经移除队列,但由于在old gen,所以未被垃圾清理的节点。

注意移除队列和被垃圾回收是两件事情。移除队列会使该节点不可达,但不一定会被 立即回收。

所以会发生多次full gc,导致程序运行变慢,虽然不会出错。

基于上面讨论,我们在移除一个节点时,应该切断next。切断next有两种方式,让next指向自身,或者让next指向null。这里不采取后者是因为next指向null有特殊含义了————表示队尾

其实总归来说主要是JVM GC的问题,如果说GC解决了跨代引用的问题,我们也没必要关注这些细节。我搜了一下,在JDK17中,AQS的cancelAcquire已经没有这个操作了,说明已经没必要了,大概率是JDK17的GC解决了这个问题。

不过其实还有一个小问题,那就是AQS是一个双项队列,按理来说还应该把prev指针指向自己或者为null,不过在其他能移除canceled node的方法中,比如acquireQueued,可以看到源码中并没有这样做。所以还是会存在跨代引用问题,一个anceled node会让一个前驱节点因为跨代引用无法回收,虽说不会像next指针那样引起大量节点无法回收,但这确实是一个存在的问题。

 类似资料:
  • 问题内容: 有人告诉我Activity.findViewById(int)方法是一种方便的方法,它在后台调用View.findViewById(int)。 我找不到任何说明Java便捷方法的文档(我只能看到iOS)。 PS:我在粗略的Google搜索过程中或通过SO prev帖子找不到任何答案。如果已经有答案了,请关闭该答案。 问题答案: 任何一种具有方法概念的语言中的便捷方法就是这样。一种使事情

  • 问题内容: 首先,是的,这是给课堂上的作业,但是我对它如何运行的缺乏了解比我想要的要高。 我们给了3类,它们是以下: SLinkedList.java 节点java 包chapter3.linkedList; 和GameEntry.java 在过去的3个小时中,我一直在听他的演讲,阅读了文本(数据结构和算法第5版),并浏览了互联网论坛和youtube视频,但是我似乎对如何利用节点/链表类。 分配的

  • 问题内容: 在C#中,您可以匿名定义委托(即使它们不过是语法糖)。例如,我可以这样做: 是否可以在Java中传递这样的代码?我正在使用处理框架,该框架具有Java的较旧版本(它没有泛型)。 问题答案: Java 8之前的版本: 最接近委托的Java是单方法接口。您可以使用匿名内部类。 Java 8及更高版本: Java 8 在该语言中添加了lambda表达式。

  • 本文向大家介绍nodejs的HTML分析利器node-jquery用法浅析,包括了nodejs的HTML分析利器node-jquery用法浅析的使用技巧和注意事项,需要的朋友参考一下 本文实例分析了nodejs的HTML分析利器node-jquery用法。分享给大家供大家参考,具体如下: 首先描述产生这篇随笔的场景:我需要获取项目在jenkins构建的最新Javascript Coverage显示

  • 问题内容: 我想知道是否有一种从Java方法调用属性的方法。我没有在Android文档中找到任何方法来做到这一点。这是我要实现的布局图: http://www.anddev.org/resources/image/2234 我知道可以通过XML进行操作,如下所示: 但是在我的情况下,我需要通过Java代码来完成此操作,因为我将动态实现另一个布局视图。为了避免将XML布局与Java代码合并,我宁愿使

  • 问题内容: 我在Java中使用以下语句: 请提出等效的C#。 问题答案: 我不知道框架中执行此操作的任何内容,但是实现起来很容易: 或者,如果您要指定计数而不是开始/结束: