所以我最近一直在考虑一些自动内存管理的想法 - 具体来说,我一直在寻找基于引用计数实现内存管理器。当然,每个人都知道循环引用会杀死天真的引用计数。解决方案:弱引用。就个人而言,我讨厌以这种方式使用弱引用(还有其他更直观的方法来处理这个,通过循环检测),但它让我思考:弱引用还有什么用处?
我认为它们必然存在某种原因,特别是在具有跟踪垃圾收集的语言中,它们不会受到循环参考陷阱的影响(C#和Java是我熟悉的,Java甚至有三种弱参考!)。但是,当我试图为他们找到一些可靠的用例时,我几乎只有像“使用它们来实现缓存”这样的想法(我已经在SO上看过几次)。我也不喜欢它,因为它们依赖于跟踪GC在不再强烈引用之后可能不会立即收集对象的事实,除非在低内存情况下。这些类型的情况对于引用计数GC是完全无效的,因为在不再引用对象之后立即销毁(除了可能在循环的情况下)。
但这真让我感到疑惑:弱引用怎么可能有用呢?如果你不能指望它引用一个对象,并且它不需要像打破周期那样,那么为什么要使用它呢?
答案 0 :(得分:38)
事件处理程序是弱引用的一个很好的用例。触发事件的对象需要引用对象以调用事件处理程序,但是您通常不希望事件生成器的引用保留以阻止事件使用者进行GC。相反,您希望事件生成器具有弱引用,然后它将负责检查引用的对象是否仍然存在。
答案 1 :(得分:5)
WeakReference引用的对象可以在gc进程之前访问。
因此,如果我们想要拥有对象的信息,只要它存在,我们就可以使用WeakReference。例如,调试器和优化器通常需要具有对象的信息,但它们不希望影响GC过程。
顺便说一句,SoftReference与WeakReference不同,因为只有在内存不足时才会收集相关对象。因此,SoftReference通常用于构建全局缓存。
答案 2 :(得分:0)
我经常将WeakReference
与ThreadLocal
或InheritableThreadLocal
结合使用。如果我们希望一个值在有意义的情况下可被多个线程访问,但稍后从这些线程中删除该值,我们实际上无法自己释放内存,因为无法篡改{{1}除当前线程之外的线程中的值。但是你可以做的是将值放在ThreadLocal
中的那些其他线程中(当创建值时 - 这假设相同的实例在多个线程中共享;请注意,这仅在只有一部分线程时才有意义应该可以访问此值,或者您只是使用静态)并在另一个WeakReference
中为一些将要删除该值的工作线程存储硬引用。然后,当值不再有意义时,您可以要求工作线程删除硬引用,这会导致所有其他线程中的值立即排队以进行垃圾回收(尽管它们可能不会立即被垃圾收集,因此值得有其他方法来阻止访问该值。)