【问题标题】:Can a weakly reachable Object be retrieved through WeakReference是否可以通过 WeakReference 检索弱可达对象
【发布时间】:2017-12-20 09:23:28
【问题描述】:

我知道WeakReference 是什么,我阅读了它的文档以及许多博客和 SO 线程。但是,我仍然不清楚以下流程是否真的会发生。

  1. 对象X被强引用strRef和弱引用weakRef引用
  2. strRef 正在随机线程上清除
  3. weakRef 在随机线程上被取消引用
  4. 上一步检索到的引用分配给strRef

关于如何在 GC 上清除弱引用有很多讨论,但据我所知,每次引用清除后都不会发生 GC。因此,如果在步骤 #2-#3 之间没有发生 GC,那么看起来弱可达对象可能会通过上面的步骤 #3 “复活”。

这样的竞态条件非常不方便,甚至很危险,因此我认为应该有一些东西可以阻止它,但我想在这里完全确定。

那么,是否有一个规范可以确保弱引用的对象不能复活,是否有任何与多线程相关的警告?

【问题讨论】:

  • 是的。推迟WeakReferenceSoftReference 阻止引用的Object 的GC,直到再次没有强引用为止。事实上,这正是PhamtomReference 不能被尊重的原因。这不是“竞争条件”,也不是“危险”。如果您不了解它是如何工作的,那只会“不方便” - 这是它必须工作的方式。
  • @BoristheSpider,我认为它是一种竞争条件,并且仅在我目前处理具有弱订阅者的 pub-sub 的情况下才危险,而不是一般情况下。这可能会导致订阅者(看似)随机收到虚假通知,即使在对它们的所有强引用都被清除后也是如此。无论如何,感谢您的输入。您是否有任何指向文档或博客文章相关部分的链接?
  • 我不明白,你为什么要依靠可达性来确定活跃度?您可以看到,在任何围绕 pub/sub 构建的框架中,演员应该在完成后显式关闭 - 这可以防止各种奇怪的行为。
  • 我正在构建一个复杂而深层次的 UI 相关类(在 Android 中)。我想我可以依靠弱引用来将这些 UI 类订阅到事件总线,这样以后就不需要取消订阅它们了。毕竟可能不是一个好主意。
  • 没错,在层次结构的每一层中,父级都告诉其子级他们当前是否可见。如果它被删除或添加到父级本身,它也会告诉它的子级。这个简单的 DAG 可以在很大程度上解决所有这些问题 - 它还允许循环检测和其他类似的功能。

标签: java multithreading garbage-collection weak-references


【解决方案1】:

因此,如果在步骤 #2-#3 之间没有发生 GC,那么上面的步骤 #3 看起来可能会“复活”一个弱可达对象。

正确,即使 GC 已经运行,也不是所有弱引用都必须被清除,例如运行次要收集时,不会清理永久空间中的对象。只有 Full GC 才能确保清除所有弱引用。

这样的比赛条件非常不方便,甚至很危险,因此我认为应该有一些东西可以阻止它,

这是您必须随时检查的内容,因为您不知道后台线程何时清除强引用。注意:清除强引用仅意味着将内存值设置为 null 仅此而已。

是否有确保弱引用对象不能复活的规范,是否有任何与多线程相关的警告?

通过在finalise 方法中设置对this 的引用,即使丢弃的对象也可以复活。我建议你不要依赖这种行为。引用设置不是消息传递的来源,也不是具有很多线程安全保证的操作。

我想我可以依靠弱引用来将这些 UI 类订阅到事件总线,这样以后就不需要取消订阅了。

您可以,但您必须检查侦听器是否仍然处于活动状态。仅仅因为你可以得到一个弱引用并不意味着你不打算丢弃它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2023-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多