WeakReference vs. "normale" Referenz

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

“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.

Object obj1 = new Object(); // RefCount(obj1) starts at 1
Object obj2 = obj1;         // RefCount(obj1) incremented to 2 as new reference is added
Object obj3 = new Object(); 

obj2.SomeMethod();
obj2 = NULL;                  // RefCount(obj1) decremented to 1 as ref goes away
obj1 = obj3;                  // RefCount(obj1) decremented to 0 and can be collected

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

WeakReference

Die WeakReference 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.

Object obj1 = new Object(); // RefCount(obj1) starts at 1
Object obj2 = new WeakReference(obj1);// RefCount(obj1) NOT incremented to 2
Object obj3 = new Object(); 

obj2.Target.SomeMethod();
obj1 = obj3;           // RefCount(obj1) decremented to 0 and can be collected
obj2 = NULL;           // RefCount(obj1) NOT changed. obj1 might be disposed already

 

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

image

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 dien 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.

Ein Weak-Singleton wird wohl einer meiner nächsten Blogs werden Winking smile.

Über Thomas Mentzel
C#, SharePoint, .NET

One Response to WeakReference vs. "normale" Referenz

  1. „Rumtime-Engine“ wäre auch ein schöner Name für eine Bar

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s

<span>%d</span> Bloggern gefällt das: