【问题标题】:Test a weak reference before using it java在使用它之前测试弱引用 java
【发布时间】:2014-12-23 21:28:42
【问题描述】:

在一个多线程的 Android 项目中,我看到这样的代码:

final WeakReference<MyClass> myClassObjectWeakRef =
                new WeakReference<MyClass>(aMyClassObject);

...然后在其他地方:

if (myClassObjectWeakRef.get() != null) {
  myClassObjectWeakRef.get().someMethod();
}

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

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

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

我非常有信心第二种方法是 100% 安全的,但我想知道是否有一些我不知道的 Java/编译器糖/魔法可以使第一种方法安全。

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

【问题讨论】:

  • 你可能是对的,;-)
  • 不应该有任何内置的 java/编译器糖/魔法来确保方法 #1 始终有效。你对情况的理解也符合我对情况的理解。

标签: java android weak-references


【解决方案1】:

第一种方法肯定是不安全的。对get 的每次调用都是独立的。没有什么可以阻止 GC 在第一个 get 之后和第二个之前清除弱可达对象。

javadoc 状态

假设垃圾收集器确定在某个时间点 对象弱可达的时间。到时候就会 原子地清除对该对象的所有弱引用和所有弱引用 对任何其他弱可达对象的引用 对象可通过一系列强引用和软引用访问。

这可以在任何时间点。调用get(),它(可能)将一个对对象的引用暂时推送到堆栈上,使该对象具有强可达性(它在线程的堆栈上),但是当与null 的比较结束时,可达性就消失了。在那一刻之后,GC 可以确定该对象是弱可达并清除其引用。然后你会得到一个NullPointerException

使用第二种方法。但请注意,通过将其分配给变量,您可以使引用的对象具有很强的可访问性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-06
    • 1970-01-01
    相关资源
    最近更新 更多