【发布时间】:2021-01-29 18:19:00
【问题描述】:
假设 ref 是一个 WeakReference 对象,它指向(或在某个时刻已经指向)一个对象 obj。如果调用 ref.get() 在执行 Reference.reachabilityFence(obj) 之前发生(或至少在程序顺序之前?),是否有机会ref.get() 的返回者可能是 null? (另外,想通过ref.get()获取refnull观察的部分再问这个问题/em> 通过队列轮询。)
我问这个问题是因为我不太确定Reference#reachabilityFence 在Java Memory Model 方面是如何工作的,尤其是当它与WeakReferences(和其他类似的引用)交互时。据我所知,以下列表是与该主题相关的规范存在的所有地方:
- (a)JSL 17.4.MemoryModel
- (b)JSL 12.6.Finalization of Class Instances,尤其是(b2)12.6.2. Interaction with the Memory Model
- (c)WeakReference.
- (d)Reference#reachabilityFence
问题在于 (c) 和 (d) 中使用的术语与 (a) 和 (b) 中使用的术语相比模糊不清。
如果开头写的问题的答案是肯定的,我怎样才能使所有 ref.get() 调用发生在某个代码点之前?如果不是,我们如何根据(a)(b)(c)(d)或其他任何地方写的规范来证明?
虽然第一个问题的答案对我来说可能已经够用了,但我也希望(c)和(d)中的规范清楚,所以让我在下面提出更多问题。
首先,(c)WeakReference 表示在某个时间点 gc 确定对象是弱可达的,同时清除弱引用,同时声明这些对象作为可最终确定的。根据 (b2),可达性检查和可终结性声明发生在 可达性决策点。所以“某个时间点”一定是可达性决策点之一,对吧?如果是这样,就会出现其他问题。 (b2) 还说可达性决策点不是代码或程序顺序中的实际点(与写入和读取不同);它们是虚拟点,仅通过前/后关系与动作相关,与程序顺序无关。所以......弱引用在决策点被清除,这不在代码的任何地方。 究竟是什么意思? WeakReference#get() 在什么情况下可以为空?不能为空?是不是我们需要的决策点和 WeakReference#get() 之间的先前后后关系?还是决策点与其他与 WeakReference#get() 有一定内存模型相关关系的动作之间的先于/后关系?
接下来,(d)可达性围栏。它说调用这个方法保持了对象的强可达性和 因此使其在调用之后不可回收。我可以将其解释为调用保持对象的强可达性直到调用 ? 从技术上讲,它并不是这样说的。但是,如果没有关于何时保持强可达性的规范,那么保持强可达性的部分是无用的。 (而另一半谈论未定义的概念“不可回收性”从一开始就没有用。)所以强可达性一直保持到调用之后——但是“之后”这个词究竟是什么意思?节目顺序?以前发生过吗?佣金发生的顺序?此外,我认为对象在(b2)中描述的某个决策点变得不可访问。什么决定了对reachabilityFence 的某个调用是否会影响某个决策点?栅栏和决策点之间的先来后到关系?显然不是,因为栅栏的调用既不是写也不是读,也不是同步动作,所以某个栅栏调用是在某个决策点之前还是之后没有区别。
我怀疑 (c) 和 (d) 太模糊,因此不可能像我的第一个问题那样回答基本问题。
【问题讨论】:
-
在“下一步,(d)reachabilityFence”之后我没有得到这部分。第一句话就像“它说一个电话……”,然后是一个问题,例如“我可以将它解释为说电话……”,使用与前一句相同的短语。当您假设一个句子的字面意思是它所说的内容时,这根本不是一种解释。但是,您继续“从技术上讲,它不是这么说的”。在那里,我迷路了。当它说它时,即使是字面意思,为什么不说它“技术上”?
-
首先,对于我无法理解的写作感到抱歉。我的大脑有点过于数学化、怀疑和不灵活。但让我解释一下我的意思。文档说[它保持强大的可达性(但直到何时才说)]并且[使对象不可回收(
-
它没有说“and”,它说“保持强可达性......因此引用的对象不可回收”。后者是前者的结果,因此即使您假设在这句话中“至少直到”仅指后者,由于逻辑依赖性,它也必须适用于前者。关于 JMM 中“至少直到”的含义,请注意语句“此方法仅适用于回收可能具有可见效果的情况,这对于具有终结器的对象是可能的......” 排序是关于栅栏前的动作和终结器或清洁器中的可见效果。
标签: java memory-model java-memory-model