弱引用/软引用/虚引用清除的并发保证

3
除了强引用之外,还有三种不同的“引用类型”:WeakReference,SoftReference和PhantomReference。可能还有其他类型,但它们要么扩展其中一种类型,要么与我的问题无关。
如果一个对象在GC周期中没有被强引用,它将被垃圾回收(即完成最后处理并从内存中删除)。但在它被收集之前,任何*Reference都会被清除 - 根据可达性条件、需要清除的引用类型、内存需求等等。
我想知道JLS是否对所有相同类型的*Reference指向同一对象的引用在原子/同时被清除做出任何保证,或者是否存在微小的机会(即“竞争条件”),某些*Reference被清除而同一类型的其他*Reference则没有被清除,因此对象有可能通过剩余的*Reference之一重新获得强引用,尽管同一类型的某些*Reference已经被清除和排队。
从不同的角度重述问题:可以安全地假设清除的*Reference意味着以前引用的对象不能通过同一类型的其他*Reference重新获得强引用吗?

我不能给你一个“硬性”的答案,但我知道这一直是Java的一个问题领域。弱引用和终结器的原始设计并不是经过深思熟虑的,而且尝试修复它是否成功也不清楚。 - Hot Licks
1个回答

4

您可以参考文档。

SoftReference:

[垃圾回收器] 可能会选择原子方式清除该对象的所有软引用,以及通过强引用链从该对象可达的任何其他软可达对象的所有软引用。

WeakReference:

[垃圾回收器] 将以原子方式清除对该对象的所有弱引用,以及通过强引用和软引用链从该对象可达的任何其他弱可达对象的所有弱引用。

对于PhantomReference,这一点无关紧要,因为无法从中检索引用对象(get始终返回null)。


是的,但是仍然存在一些关于是否(对于一个特定对象,例如)所有软引用在非GC线程方面是否会被原子地清除的余地。或者,如果一个(而不是所有多个)未被清除的软引用可能会使一个对象复活... - user2864740
2
@user2864740 文档中说clear是原子性的。哪里有余地?它要么是原子性的,要么不是。 - Radiodef
我认为JVM在GC周期中基本上是冻结的(即可以假定任何GC操作与内存模型具有原子性)。我的问题是,如果文档中的“原子性”意味着“一次性清除所有这些引用”,还是只有“所有这些引用各自单独清除”。请明确回答我的问题:清除的引用是否意味着以前引用的对象不能通过相同类型的引用(或同类或更强的纠缠链)来恢复? - Robin479
2
@Robin479,文档清楚地说明:“原子性地清除对该对象的所有弱引用以及从该对象通过一系列强引用和软引用可达的任何其他弱可达对象的所有弱引用”。您在上一句中描述的引用要么包含在该规范中,要么不存在。逐个引用地进行“原子性”清除是没有意义的。 - user207421
1
我猜你是在问我是否认为文档中使用的措辞不明确,但我认为并不是这样。 "atomically clear all" 是非常明确的。 - Radiodef
对我来说,文档中的措辞有些模糊,因为它取决于你在句子中放置重音/口音的位置(参见[https://en.wikipedia.org/wiki/Prosodic_stress])。这就是为什么比起简单的主谓宾形式,更详细的(英语)句子不是传递信息的好方式 _(万岁Web 3.0!)_,并且不应该出现在规范中。我的原始问题,如果清除了“参考资料意味着前面的指代也不能以其他方式恢复”,将保持未回答状态,尽管已经给出了一些不确定的RTFM答案。 - Robin479

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接