java.lang.ref.Reference 方法的内存语义

Memory semantics of java.lang.ref.Reference methods

我正在开发一些处理引用对象的并发算法。我正在使用 java 17.

问题是我不知道 get、clear 或 refersTo 等操作的内存语义是什么。它没有记录在 Javadoc 中。

查看OpenJdk的源代码,引用对象没有修饰符,比如volatile(而引用队列的下一个指针是volatile)。 此外,get 实现是微不足道的,但它是一个内在的候选者。 clear 和 refersTo 是原生的。所以我不知道他们到底是做什么的。

当 GC 清除引用时,我必须假设所有线程都会看到它被清除,否则它们会看到对对象(正在处理中)的引用被垃圾收集,但这只是一个非正式的猜测。

所有这些操作的内存语义是否有任何保证?

如果没有,是否有办法通过在调用这些操作之一之后在 and/or 之前调用例如围栏操作来获得对易失性访问的相同保证?

当您在引用对象上调用 clear() 时,它只会清除这个特定的 Reference 对象,而不会对您的应用程序的其余部分产生任何影响,也没有特殊的内存语义。这与您在代码中看到的完全一样,将 null 赋值给没有 volatile 修饰符的字段。

心灵the documentation of clear():

This method is invoked only by Java code; when the garbage collector clears references it does so directly, without invoking this method.

所以这与GC清除引用事件无关。当 GC 清除引用时,您的假设“所有线程都会看到它被清除”是正确的。 documentation of WeakReference 状态:

Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references.

所以在这一点上,不仅所有的线程都会同意一个弱引用已经被清除,他们也会同意对同一个对象的所有弱引用都已经被清除。可以在 SoftReferencePhantomReference.

找到类似的声明

The Java Language Specification, §12.6.2. Interaction with the Memory Model 指的是可能发生这种原子清除的点,如 可达性决策点 。它根据“comes-before di”和“comes-after di 指定这些点与其他程序操作之间的交互”关系,最重要的是:

If r is a read that sees a write w and r comes-before di, then w must come-before di.

If x and y are synchronization actions on the same variable or monitor such that so(x, y) (§17.4.4) and y comes-before di, then x must come-before di.

因此,GC 操作将被插入到同步顺序中,即使是快速读取也无法破坏它,但重要的是要记住,应用程序不知道可达性决策点的确切位置。它显然介于 get() 返回非 null 引用或 refersTo(null) 返回 false 的最后一点和 get() 返回 null 的第一点之间] 或 refersTo(null) 返回 true.

对于实际应用,一旦引用报告对象被垃圾回收,您就可以确定它不会在任何地方重新出现¹,这一事实就足够了。只需将引用对象保密,以确保没有人对其调用 clear()

¹ 抛开“终结器复活”之类的事情