Weak Reference vs. Strong Referenz

DE   C#

Mit Referenzen und dem Verwerfen (Disposen) von Objekten haben wir uns mit C++ noch herumgeschlagen. Jetzt kümmert sich bei Java oder .NET die Runtime-Engine und der Garbage Collector genau um dieses Thema. Warum also noch damit beschäftigen? Weil es manchmal noch notwendig ist.

Strong Reference (“Normale” Referenz)

Der Ablauf für “Reference Counting” ist grundsätzlich banal. Mit jedem Verweis auf ein Objekt wird ein Zähler inkrementiert, mit jedem gelöschten Verweis wird der Zähler dekrementiert. Ist der Zähler ‘0’, dann kann das Objekt gelöscht werden. Hier etwas Code zum verdeutlichen.

Standardmäßig werden Objekte und deren Referenzen so verwaltet. Das funktioniert auch fast immer ganz gut, aber nur fast!

Weak Reference (“Schwache” Referenz)

Die Weak Reference ist, einfach ausgedrückt, eine Referenz die den Zähler nicht erhöht. Über die Eigenschaft “IsAlive” kann festgestellt werden, ob das Objekt bereits verworfen wurde. Mit der Eigenschaft Target kann, falls IsAlive == true ist, auf das Objekt zugegriffen werden.

Hier noch einmal grafisch was passiert, und wann eine Referenz verworfen wird.

Weak References

Es kann also eine Referenz auf ein Objekt gespeichert werden, ohne dass dieses einen Einfluss auf den Garbage Collector hat.

Und nun?

Spontan fallen mir hierzu zwei Szenarien ein. Das erste Szenario ist eine Identity Map, die eine Referenz nur dann Speichert und das „singleton Objekt” zurück gibt, wenn es noch eine Stelle im Programm gibt, die dieses Objekt verwendet. Ansonsten wird das Objekt verworfen und bei einer erneuten Anfrage ein neues Objekt gelesen. Mehr dazu im Pattern of the Week #9.

Alternativ kann die WeakReference in einem Singleton verwendet werden. Normalerweise speichert man die Referenz auf das Objekt direkt. Wenn man für ein Singleton definiert, das eine oder keine Instanz existieren darf, also eine Instanz verworfen werden darf, wenn sie nicht mehr verwendet wird, kann man das auch als WeakReferenz implementieren. Beispiel:

  • A erzeugt beim Aufruf des Weak-Singleton eine neuen Instanz
  • B bekommt beim Aufruf das Weak-Singleton zurück
  • A löscht die Referenz auf das Weak-Singleton
  • B löscht die Referenz auf das Weak Singleton
  • Der GC löscht die Referenz

Nun B erzeugt beim Aufruf des Weak-Singleton eine neue Instanz A bekommt beim Aufruf des Weak-Singleton diese neue Instanz zurück

Insgesamt werden also zwei Instanzen erzeugt, das Weak-Singleton stellt aber sicher, dass zu einem Zeitpunkt maximal eine Instanz des Singleton existiert.

Resümee

Eine WeakReference gibt und also mehr Kontrolle über den Lebenszyklus eines Objektes und kann verhindern, dass verhindert wird, das ein Objekt verworfen wird. Man sollte diese Möglichkeit im Hinterkopf behalten, falls mal ein solcher Fall implementiert werden muss, z.B. wenn eine IdentityMap einen Speicherüberlauf erzeugt.

(Dieser Artikel wurde von meinem alten Blog migriert
Written on May 30, 2012