在阅读LinkedBlockingQueue源码时,有段关于弱一致性迭代器实现的注释:
/*
* To implement weakly consistent iterators, it appears we need to
* keep all Nodes GC-reachable from a predecessor dequeued Node.
* That would cause two problems:
* - allow a rogue Iterator to cause unbounded memory retention
* - cause cross-generational linking of old Nodes to new Nodes if
* a Node was tenured while live, which generational GCs have a
* hard time dealing with, causing repeated major collections.
* However, only non-deleted Nodes need to be reachable from
* dequeued Nodes, and reachability does not necessarily have to
* be of the kind understood by the GC. We use the trick of
* linking a Node that has just been dequeued to itself. Such a
* self-link implicitly means to advance to head.next.
大概直译下是:
为了实现弱一致性迭代器,我们似乎需要保证前一个出队结点到所有结点的GC可达性。这可能会导致两个问题:
-允许行为异常(rogue)的迭代器会造成无限的内存保留
-如果一个结点在活着的时候进入老年代了(tenured),迭代器会造成旧结点到新结点的跨代联系,分代GC很难处理这种链接,导致重复的老年收集(major collections)
不过,只要有出队的结点需要可达到未删除的结点这个概念,可达性就没有必要由GC理解。我们会通过将已离队的结点连接到自己的方法,这样的自我连接暗指迭代器需要到head.next结点
个人理解下,保证前一个出队结点到所有结点的GC可达性的队列应该是这样的(current是迭代器的指针):
第一点倒好理解,current和head间的出队结点数量是可以无限增加的——只要current不动,队列又不断地入队出队,current和head间的结点就会不断地增加,导致这部分的内存也不断地增加。
但是第二点就不清楚具体是什么意思,为什么旧结点变成老年代后,和新生代结点的跨代联系(cross-generational linking)会导致更频繁的major GC呢?是因为离队的结点理应被GC回收却回收不了,变成老年代之后占据了老年代的空间,老年代剩余空间变少导致major GC更频繁吗?