在使用java之前测试弱引用

Geo*_*ges 21 java android weak-references

在多线程Android项目中,我看到的代码如下:

final WeakReference<MyClass> myClassObjectWeakRef =
                new WeakReference<MyClass>(aMyClassObject);
Run Code Online (Sandbox Code Playgroud)

......然后在其他地方:

if (myClassObjectWeakRef.get() != null) {
  myClassObjectWeakRef.get().someMethod();
}
Run Code Online (Sandbox Code Playgroud)

我很确定在检查和引用的使用之间可能存在竞争条件,如果对象的最后一个强引用是在另一个线程中的两个之间释放,但我找不到任何文档或任何人/ /谁可以比"你可能是对的"更好地证实这一点.

我认为测试和使用弱引用的唯一正确方法是这样做的:

MyClass myObject = myClassObjectWeakRef.get();
// we now have a strong reference, or null: standard checks apply.
if (myObject != null) {
  myObject.someMethod();
}
Run Code Online (Sandbox Code Playgroud)

我非常有信心,第二个方法是100%安全的,但我不知道是否有一些Java /编译糖/魔法,我不知道,这会使得第一种方法是安全的.

那么,第一种方法是否100%安全?

Sot*_*lis 14

第一种方法绝对不安全.每次通话get都是独立的.没有什么能阻止GC在第一个get和第二个之后清除弱可达对象.

javadoc的状态

假设垃圾收集器在某个时间点确定对象是弱可达的.在那个时候就会给该对象并自动清除所有弱引用,以从该物体是通过可达强和软引用链中的任何其他弱可到达对象的所有弱引用.

这可以在任何时间点.调用get()(可能)推送对堆栈中对象的引用会暂时使对象强烈可达(它位于线程的堆栈上),但是在null完成比较时,该覆盖能力会消失.在那之后,GC可以确定该对象是弱可达的并清除其引用.然后你会得到一个NullPointerException.

使用第二种方法.但请注意,通过将其分配给变量,您可以使引用的对象可以很容易地访问.