Weak references - how useful are they?

10,293

Solution 1

Event handlers are a good use case for weak references. The object that fires events needs a reference to the objects to invoke event handlers on, but you typically don't want the event producer's reference holding to prevent the event consumers from being GC'd. Rather, you'd want the event producer to have a weak reference, and it would then be responsible for checking whether the referenced object was still present.

Solution 2

I often use WeakReference in conjunction with ThreadLocal or InheritableThreadLocal. If we want a value to be accessible to a number of threads while it is meaningful, but then later remove the value from those threads, we can't actually free the memory ourselves because there is no way to tamper with a ThreadLocal value in a thread other than the current one. However what you can do is put the value in a WeakReference in those other threads (when the value is created - this assumes the same instance is shared across multiple threads; note that this is only meaningful when only a subset of threads should have access to this value or you'd just use statics) and store a hard reference in another ThreadLocal for some worker thread that is going to be removing the value. Then when the value ceases to be meaningful, you can ask the worker thread to remove the hard reference, which causes the values in all other threads to be immediately enqueued for garbage collection (although they may not be garbage-collected immediately so it's worthwhile to have some other way to prevent the value from being accessed).

Share:
10,293
Ken Wayne VanderLinde
Author by

Ken Wayne VanderLinde

Updated on June 19, 2022

Comments

  • Ken Wayne VanderLinde
    Ken Wayne VanderLinde about 2 years

    So I've been mulling over some automatic memory management ideas lately - specifically, I've been looking at implementing a memory manager based on reference counting. Of course, everyone knows that circular references kill naive reference counting. The solution: weak references. Personally, I hate using weak references in this way (there are other more intuitive ways of dealing with this, via cycle detection), but it got me thinking: where else could a weak reference be useful?

    I figure that there must be some reason they exist, especially in languages with tracing garbage collection, which do not suffer from the cyclic reference pitfall (C# and Java are the ones I'm familiar with, and Java even has three kinds of weak references!). When I've tried to find some solid use-cases for them, though, I pretty much just got ideas like "Use them to implement caches" (I've seen that a few times on SO). I don't like that either, since they rely on the fact that a tracing GC will likely not collect an object immediately after it's no longer strongly referenced, except in low-memory situations. These kinds of cases are absolutely invalid with reference counting GC since an object is destroyed immediately after it is no longer referenced (except possibly in the case of cycles).

    But that really leaves me wondering: How can a weak reference possibly be useful? If you can't count on it referencing an object, and its not needed for things like breaking cycles, then why use one?

  • supercat
    supercat over 12 years
    They'd be a better use case for weak references if there were a delegate type which would not keep the target alive, but would invalidate itself if the target were collected, and if Delegate.Combine knew enough about this delegate type to skip invalidated instances when combining delegates. Otherwise the .net event pattern has no good remedy for a scenario where many short-lived objects are created, subscribed to events from long-lived objects, and abandoned.
  • Ken Wayne VanderLinde
    Ken Wayne VanderLinde over 12 years
    @supercat: Well, this isn't a question about .Net, or about any other platform or language - it's just about places where weak-references could be useful. Ironically, the project I was working on was in C++ (no event model), and it involved both reference counting and event handlers!
  • Pacerier
    Pacerier almost 7 years
    Re "..when the value is created..", Why do you need to ensure that its at the creation stage? Couldn't you pass the object reference to the other threads after creation?
  • Adam Burley
    Adam Burley almost 7 years
    @Pacerier yes, if you had access to the code running in those other threads to inform those threads to expect a value and add it to their ThreadLocal. However, often we don't have access to the code of those threads, because they were created by some third-party library (for example logging library, non-blocking IO library etc). We can't pass any message to those threads or tell them what to do after they have started. However we can tell them what to do when they start, via the InheritableThreadLocal.childValue method (or indeed just the default behaviour of InheritableThreadLocal).
  • Markus Zeller
    Markus Zeller almost 4 years
    Why not just unsubscribe? Wouldn't it remove at least one reference and shrink the queue?