# Java Garbage Collector Frage (Singleton Pattern)



## Mastereye (29. Feb 2008)

Hi,

ich hab mal eine spezifische Frage zum Java Garbage Collector. Wenn ich eine Singleton Pattern implementation habe, bedeutet das ja, dass ich zur Laufzeit des Programms nur eine Instance habe (sofern getInstance mindestens einmal aufgerufen wurde). Meine Frage ist nun, ob die Instance vom Garbage collector erfasst wird, wenn ich sie zur Laufzeit wieder null setze, wenn ich also in dem folgenden Code die release function aufrufe.


```
public class Singleton {
	
	private static Singleton instance = null;
	
	public static Singleton getInstance() {
		if (instance == null)
			instance = new Singleton();
			
		return instance;
	}
	
	private Singleton() {
		// do something
	}
	
	
	public static void releaseSingleton() {
		instance = null;
	}
	
}
```


Vielen Dank für eure Hilfe,

Andreas


----------



## Wildcard (29. Feb 2008)

sofern nirgends sonst eine Referenz gespeichert wurde, ja.
Sieht mir allerdings äusserst gefährlich aus. Dadurch kannst du problemlos mehrere Singelton Instanzen bekommen, was die ganze Sache sozusagen nutzlos macht.


----------



## Saxony (3. Mrz 2008)

Wildcard hat gesagt.:
			
		

> Dadurch kannst du problemlos mehrere Singelton Instanzen bekommen, was die ganze Sache sozusagen nutzlos macht.



Schöne Erklärung zu den Risiken bei Singletons.

bye Saxony


----------



## quippy (3. Mrz 2008)

Da muss ich doch gleich mal eine Verständnisfrage zu loswerden. Der Code


```
public static DoubleCheckedLockingSingleton getInstance() {
        if (instance == null) {
            synchronized(DoubleCheckedLockingSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckedLockingSingleton();
                }
            }
        }
        return instance;
    }
```

Wird als unsicher bezeichnet, da die Anweisung "new", also die Speicherzuweisung, in der VM nicht atomar ist und von einem Thread unterbrochen werden könnte. 

Das ist zwar richtig, allerdings ist das doch völlig egal, denn durch den "synchronized"-Block wird es als atomare Anweisung zusammengefasst...

Ich stelle mir das folgendermaßen vor
a) Mehrere Threads fordern eine Instanz via "getInstance" an
b) alle laufen durch den ersten IF, da noch keine Instanz existiert
c) *nur einer* wird den Synchronized-Block betreten, *alle anderen* müssen warten
d) Wenn dieser eine den Syncho-Block verlässt, hat "instance" einen Wert
d') Erfolgt eine Unterbrechung innerhalb des synchro-Blocks, ist der semaphore noch immer gesetzt und die wartenden komme noch immer nicht an die Reihe.
e) Die restlichen wartenden betreten hübsch hintereinander den Syncho-Block, evaluieren die Anfrage mit false und begnügen sich mit dem Inhalt von "instance"

So stelle ich mir das vor und frage mich daher, wie die Unterbrechung der Allozierung ein Problem darstellen soll. Was habe ich da nun nicht verstanden?


----------



## SlaterB (3. Mrz 2008)

in dem Artitek steht es wirklich etwas unklar, gelinkt ist aber auch
http://en.wikipedia.org/wiki/Double-checked_locking
und da wirds deutlicher: 

das Objekt könnte als initialisiert gelten und dann kommt ein neuer Thread in die Operation und überwindet das ERSTE if (nicht das zweite) und arbeitet mit der noch nicht wirklich tollen instance

falls es wer weiß, ist 
Object x =  new DoubleCheckedLockingSingleton(); 
instance = x;
dann sicher?


----------



## quippy (3. Mrz 2008)

SlaterB hat gesagt.:
			
		

> in dem Artitek steht es wirklich etwas unklar, gelinkt ist aber auch
> http://en.wikipedia.org/wiki/Double-checked_locking
> und da wirds deutlicher:
> 
> ...



Ah! D.h. wir haben eine Instanz, aber der Konstruktor war noch nicht aufgerufen worden... Oja, das ist natürlich möglich und würde durch Deine Zeilen dann wahrscheinlich umgangen. Es sei denn, der Compiler optimiert die unnötige Zuweisung weg.

Aber "volatile"-Deklaration soll ja ab Java5 das Problem beheben...

Ich hatte bisher zwar nie endgültig verstanden, was hier nicht funktioniert (nun schon), aber da mir das das Konstrukt mit dem doppelten if-synchronized-if sowieso schon nie gefallen hatte (ist unleserlich und irgendwie auch nicht hübsch - viel zu technisch getrieben), habe ich es auch immer dem Classloader anvertraut, die Instanzen im Vorfeld zu beschaffen - also so

```
private static final myObject = new MyObject();

// ggf auch
static
{
   //was auch immer noch fehlt!
}
```

und gut iss...


----------



## Wildcard (3. Mrz 2008)

Für mich bietet ein Singleton nichts, was ich nicht auch mit statischen Methoden erreichen könnte, daher verwende ich auch keine Singletons mehr.


----------



## maki (3. Mrz 2008)

quippy, 
hier wird dieses Problem ganz gut beschrieben:

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Kann Wildcard und Saxony nur beipflichten.

Zusätzlich frage ich mich warum wirklich meint jeder seine "programmers bitch" (=Singleton) immer als lazy initialisation implementieren zu müssen obwohl 99,9% der Singleton Klassen immer benuzt werden ...


----------



## SlaterB (3. Mrz 2008)

es gibt ja auch kleinere Singletons, pro Thread, pro DB-Transktion, pro Benutzer, pro Anwendungsteil, 
da kommt man mit statisch nicht weit,
vom Verzicht auf Vererbung, Interface usw. ganz zu schweigen,
(edit: aber dann hat man sich auch meist gar nicht mit synchronzid & Co. rumzuschlagen)

beim Lazy gehöre ich wohl zu den 0.01%, 
die 7x 500ms DB-Abfragen spare ich doch gerne ein wenn ich nur 3 von 10 Standard-Daten-Mengen für einen bestimmten Durchlauf benötige


----------



## maki (3. Mrz 2008)

> beim Lazy gehöre ich wohl zu den 0.01%,
> die 7x 500ms DB-Abfragen spare ich doch gerne ein wenn ich nur 3 von 10 Standard-Daten-Mengen für einen bestimmten Durchlauf benötige icon_wink.gif


Das sehe ich ein SlaterB 

Ich sehe die meisten Singletons als DaoFactory und ähnliches, also in Situation, in denen man immer diese eine Instanz braucht, da ist die Sache mit der lazy init. einfach fehl am Platz, für die anderen gibt's die Singleton Holder Variante, geht auch ohne synchronized und ist trotzdem threadsicher.


----------



## Wildcard (3. Mrz 2008)

> es gibt ja auch kleinere Singletons, pro Thread, pro DB-Transktion, pro Benutzer, pro Anwendungsteil,
> da kommt man mit statisch nicht weit,


Wenn es mehr als ein Objekt einer Klasse in einer VM gibt, ist sie kein Singleton. In verteilten Umgebungen (zB RMI), kann es sogar noch globaler sein.


> vom Verzicht auf Vererbung, Interface usw. ganz zu schweigen,


Bei Interfaces und Vererbung kann ein Singleton durchaus Sinn machen.
Nach meiner Erfahrung wird es aber öfter falsch, als richtig eingesetzt. Manchmal frage ich mich, ob angehende Java Programmierer 'Angst' vor static haben und deshalb meinen ein Singleton verwenden zu müssen. An statischen Methoden ist nichts verkehrt  ???:L


----------



## quippy (3. Mrz 2008)

Es gibt da einen ganz klaren Grundsatz, der Static contra Instanz trennt:

Man erzeugt keine Instanz einer Klasse, wenn die Klasse nicht eine einzige Instanzvariable hat. Oder als "OO-Talk": habe ich mehrere Ausprägungen einer Klasse, stelle ich diese als Instanz der Klasse dar.

Im Umkehrschluss kann man nun sagen, daß ein Singleton zwar eine Ausprägung einer Klasse sein kann (weil die Klasse Instanzvariablen besitzt), allerdings einmalig ist (liegt in der Natur eines Singletons). Ergo kann es keine unterschiedlichen Ausprägungen geben - also könnte man es auch als static lösen.

Einzig wenn man mit Ableitungen arbeiten muss, also seinen Singleton in unterschiedlichen Varianten haben will, macht das wieder Sinn.


----------



## Wildcard (3. Mrz 2008)

quippy hat gesagt.:
			
		

> Einzig wenn man mit Ableitungen arbeiten muss, also seinen Singleton in unterschiedlichen Varianten haben will, macht das wieder Sinn.


Und genau dafür ist ein Singleton auch gedacht. Nur wird es sehr selten so verwendet.


----------



## quippy (4. Mrz 2008)

Wildcard hat gesagt.:
			
		

> quippy hat gesagt.:
> 
> 
> 
> ...



Wer als einziges Werkzeug einen Hammer kennt, ist geneigt, jedes Problem als Nagel zu sehen


----------

