Java Garbage Collector Frage (Singleton Pattern)

Status
Nicht offen für weitere Antworten.

Mastereye

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

Code:
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
 
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.
 
Da muss ich doch gleich mal eine Verständnisfrage zu loswerden. Der Code

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?
 
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?
 
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:

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?

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
Code:
private static final myObject = new MyObject();

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

und gut iss...
 
Für mich bietet ein Singleton nichts, was ich nicht auch mit statischen Methoden erreichen könnte, daher verwende ich auch keine Singletons mehr.
 
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 😉
 
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.
 
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
 
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.
 
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.
 
Wildcard hat gesagt.:
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.

Wer als einziges Werkzeug einen Hammer kennt, ist geneigt, jedes Problem als Nagel zu sehen 😀
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben