Singleton

Hi, i have a basic question, how many instances of a singleton will be created in a multi threaded environment. 1. As every thread has it's own object... does it mean, every thread has its own instacne of singleton class? thanks in advance..thanksSJ
[292 byte] By [_AM__a] at [2007-10-2 21:21:50]
# 1
Normally only one instance exists.For exceptions to this, have a look at this article:[url=" http://java.sun.com/developer/technicalArticles/Programming/singletons/"]When is a Singleton not a Singleton[/url]
horstmeyera at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

> i have a basic question, how many instances of a

> singleton will be created in a multi threaded

> environment.

It depends on how you implement the Singleton. If it is implemented correctly, using a static initialisation, there will be one instance.

> 1. As every thread has it's own object... does it

> mean, every thread has its own instacne of singleton

> class?

No. It is not possible to state with any certainty the number of instances. There is a race condition. There could be one instance, there could be the same number of instances as threads, or anywhere between. The number of instances could be different each time it's run.

If it was deterministic it could be fixed, but Singleton is not deterministic when lazy initialisation is used.

MartinS.a at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 3
This sentence > No. It is not possible to state with any certainty the number of instances. should have included the following :... when lazy initialisation is used.
MartinS.a at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 4
> If it was deterministic it could be fixed, but> Singleton is not deterministic when lazy> initialisation is used.How do you figure? As long as it it synchronized properly, you can predict the number of instances per class loader.
dubwaia at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

> > If it was deterministic it could be fixed, but

> > Singleton is not deterministic when lazy

> > initialisation is used.

>

> How do you figure? As long as it it synchronized

> properly, you can predict the number of instances per

> class loader.

It cannot be synchronized _properly_ because the optimiser is allowed to delay the unlock at the end of the synchronized block.

Therefore a second thread may still attempt to reference the singleton before the construction is complete in another thread.

This explains why much more completely than I could.

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

MartinS.a at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

What do you mean "every thread has it's own object." Are you talking about local objects here? A thread and an object are two different things. There is a Thread object, but its not exactly the same as the thread it creates.

TO put it simply, threads have nothing to do with this. This is a question of classloaders.

_dnoyeBa at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 7

> This explains why much more completely than I could.

>

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

Interesting. However, the issue seems to be fixed and you now can make sure to have onle one instance (per classloader) by declaring the variable that references the singleton to be volatile.

Note the "[url=http://www.cs.umd.edu/~pugh/java/memoryModel]Work is underway[/url]"-link near the end of that page which leads to a reference page for JSR 133. With JDK 1.5 this is included in the VM specification (see [1])

[1] http://java.sun.com/docs/books/vmspec/2nd-edition/jvms-clarify.html

horstmeyera at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

> It cannot be synchronized _properly_ because the

> optimiser is allowed to delay the unlock at the end

> of the synchronized block.

>

> Therefore a second thread may still attempt to

> reference the singleton before the construction is

> complete in another thread.

>

> This explains why much more completely than I could.

>

> http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleChe

> ckedLocking.html

I am very familiar with that article. You are reading into things. It's about how double-check locking is broken. It doesn't claim that synchronization is broken. You don't have to use a double-checked locking to implement a singleton. If you synchronize properly it works perfectly (assuming the jvm is compliant.)

dubwaia at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 9
Direct you attention to the threadsafe example in listing 2. http://www-128.ibm.com/developerworks/java/library/j-dcl.html?loc=jI find it strange that this myth that lazy loaded singletons cannot be written in Java exists. This isn't the first time I've had this debate.
dubwaia at 2007-7-14 0:31:56 > top of Java-index,Other Topics,Patterns & OO Design...
# 10

> Note the

> "[url=http://www.cs.umd.edu/~pugh/java/memoryModel]Wor

> k is underway[/url]"-link near the end of that page

> which leads to a reference page for JSR 133. With JDK

> 1.5 this is included in the VM specification (see

I hadn't realised "Work is underway" was out of date, and JSR133 had been included in 1.5.

MartinS.a at 2007-7-14 0:31:57 > top of Java-index,Other Topics,Patterns & OO Design...
# 11

> It's about how double-check

> locking is broken. It doesn't claim that

> synchronization is broken.

The following paragraph states explicitly that synchronization doesnt fix double check locking.

"The rules for synchronization don't work that way. The rule for a monitorexit (i.e., releasing synchronization) is that actions before the monitorexit must be performed before the monitor is released. However, there is no rule which says that actions after the monitorexit may not be done before the monitor is released. It is perfectly reasonable and legal for the compiler to move the assignment helper = h; inside the synchronized block, in which case we are back where we were previously. Many processors offer instructions that perform this kind of one-way memory barrier. Changing the semantics to require releasing a lock to be a full memory barrier would have performance penalties."

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

> You don't have to use a

> double-checked locking to implement a singleton.

Which is why I originally stated that singleton should be statically initalised.

> If you synchronize properly it works perfectly (assuming

> the jvm is compliant.)

The basic claim holds true, that syncronization doesnt fix double check locking, even post JSR 133 volatile must be used.

MartinS.a at 2007-7-14 0:31:57 > top of Java-index,Other Topics,Patterns & OO Design...
# 12

> Direct you attention to the threadsafe example in

> listing 2.

>

> http://www-128.ibm.com/developerworks/java/library/j-dcl.html?loc=j

>

> I find it strange that this myth that lazy loaded

> singletons cannot be written in Java exists. This

> isn't the first time I've had this debate.

Well JSR133 aside, that article also states that double checked locking is broken.

Summary

In an effort to avoid costly synchronization in singletons, programmers, quite ingeniously, invented the double-checked locking idiom. Unfortunately, it was not until this idiom was in fairly wide use that it became apparent that it is not a safe programming construct due to the current memory model. Work is underway to redefine areas of the memory model that are weak. However, even under the newly proposed memory model, double-checked locking will not work. The best solution to this problem is to accept synchronization or use a static field

MartinS.a at 2007-7-14 0:31:57 > top of Java-index,Other Topics,Patterns & OO Design...
# 13

> > It's about how double-check

> > locking is broken. It doesn't claim that

> > synchronization is broken.

>

> The following paragraph states explicitly that

> synchronization doesnt fix double check locking.

>

> "The rules for synchronization don't work that way.

> The rule for a monitorexit (i.e., releasing

> synchronization) is that actions before the

> monitorexit must be performed before the monitor is

> released. However, there is no rule which says that

> actions after the monitorexit may not be done before

> the monitor is released. It is perfectly reasonable

> and legal for the compiler to move the assignment

> helper = h; inside the synchronized block, in which

> case we are back where we were previously. Many

> processors offer instructions that perform this kind

> of one-way memory barrier. Changing the semantics to

> require releasing a lock to be a full memory barrier

> would have performance penalties."

>

> http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleChe

> ckedLocking.html

>

> > You don't have to use a

> > double-checked locking to implement a singleton.

> Which is why I originally stated that singleton

> should be statically initalised.

But it doesn't have to be. You wrote (or at least implied) that one can't properly do it otherwise. You can do it with proper synchronization i.e. no double-checked locking.

> > If you synchronize properly it works perfectly

> (assuming

> > the jvm is compliant.)

>

> The basic claim holds true, that syncronization

> doesnt fix double check locking, even post JSR 133

> volatile must be used.

You brought up double-checked locking. It has nothing to do with my point. Again, you do not need double-checked locking:

static synchronized Singleton getInstance()

{

if (instance == null) instance = new Singleton();

return instance;

}

The above is perfectly threadsafe.

dubwaia at 2007-7-14 0:31:57 > top of Java-index,Other Topics,Patterns & OO Design...
# 14
> Well JSR133 aside, that article also states that> double checked locking is broken.And what does that have to do with the price of tea in China?
dubwaia at 2007-7-14 0:31:57 > top of Java-index,Other Topics,Patterns & OO Design...
# 15

> You brought up double-checked locking. It has

> nothing to do with my point. Again, you do not need

> double-checked locking:

> > static synchronized Singleton getInstance()

> {

> if (instance == null) instance = new

> Singleton();

>

>return instance;

>

>

> The above is perfectly threadsafe.

not to dispute you, but rather to support your point, that particular article DOES present a very slick alternative of loading that singleton from within another class, thus using the static initialization to ensure that the singleton is only created once, but also allow it to be lazily initialized, because the containing class is.

That truly is a neat idea, and I find it odd that nobody has even mentioned it. Is there some reason why this solution would not suffice? Really, the whole question here is about lazy intialization of singletons, not about the double checked locking.

guitar_man_Fa at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 16

> not to dispute you, but rather to support your point,

> that particular article DOES present a very slick

> alternative of loading that singleton from within

> another class, thus using the static initialization

> to ensure that the singleton is only created once,

> but also allow it to be lazily initialized, because

> the containing class is.

>

> That truly is a neat idea, and I find it odd that

> nobody has even mentioned it. Is there some reason

> why this solution would not suffice? Really, the

> whole question here is about lazy intialization of

> singletons, not about the double checked locking.

I think that in practice that works but they way I read the JLS, it says to me that any class can be loaded at any time by the VM. This is disputed.In any event, the static initializer works in almost all cases anyway and that's what I normally use.

One note on using volatile to fix double-checked locking: From what I understand, volatile now carries pretty much the same overhead as synchronization so there's not much benefit to doing it that way.

dubwaia at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 17

MartinS I am familiar with that paper and read it cover to cover a few times. I do believe I found a flaw in it years ago, but anyway I was in agreement with it for long time.

In any event this is becoming a play on words. Double checked locking can not be fixed with synchronization because once you add synchronization its no longer "double checked locking."

You don't need double checked locking to produce a singleton. Just locking.

_dnoyeBa at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 18

> I think that in practice that works but they way I

> read the JLS, it says to me that any class can be

> loaded at any time by the VM. This is disputed.In

> any event, the static initializer works in almost all

> cases anyway and that's what I normally use.

yeah, I took a look through the JLS before posting that, too. But I think that the class loading time may be irrelevant. What IS relevent is the initialization time. And the JLS does specifically define WHEN a class is initialized.

I'm not sure, however, whether this is a guideline or a hard fast rule, because it does not use any clear, strong words that would indicate that this MUST be the case.

Also, I beleive when you look at the JVMS, it does define WHEN a class gets loaded, if it is indeed relavent. But again, I'm not totally sure of this.

I suppose its a question of the use of Lazy Initialization. If the intialization isn't complex, you're probably right. Just use the static initializer. On the other hand, when Lazy Initialization IS rquired, this seems like a CLEAN way to do it, and requires only a single check with absolutely ZERO synchronization once it has been intialized once.

I think that makes it worth looking into, in some cases, at least. That's my take on it.

- Adam

guitar_man_Fa at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 19

NOTE: I missed the point on intialization vs. loading at first. I'm not going to change it now, though.

> yeah, I took a look through the JLS before posting

> that, too. But I think that the class loading time

> may be irrelevant. What IS relevent is the

> initialization time. And the JLS does specifically

> define WHEN a class is initialized.

If you read closely, it basically says 'the VM can preload in the following cases' and links to a laundry list which includes 'if it feels the need to do so.' What it does ssay is that it can't throw errors that occur during loading until you reference it even if it preloads the class. But it clearly states that VM the need only load the class prior to it's first use. I can see how that could be interpreted to say "and not earlier than that" but other sections explicitly state that it can pre-load any class.

What I don't get about this is that if the VM can preload one class, why wouldn't it be able to preload this other class?

I've actually seen errors occur because of preloading in an application server so this isn't academic.

dubwaia at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 20

> yeah, I took a look through the JLS before posting

> that, too. But I think that the class loading time

> may be irrelevant. What IS relevent is the

> initialization time. And the JLS does specifically

> define WHEN a class is initialized.

Sorry, I missed the point here. I recall from just a few weeks ago that the spec says (or at least implies) that the class can initialize when loaded.

I may be thinking of an older version of the spec because the new one seems much more strict.

But here's relevant text that I feel backs up my main assertion.:

"Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization."

dubwaia at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 21
The Initialize-on-demand holder pattern is a viable alternative to volatile, static initialization or synchronized getInstance() methods. See http://www-128.ibm.com/developerworks/java/library/j-jtp03304/ for an excellent discussion of the topic.
jonathan.scuddera at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 22

Don't understand why the basic pattern definition is being twisted? I am horrified to read statements like "It depends on how you implement Singleton". If this so called 'version' of Singleton does not restrict object creation (for more than one instances) then it is not a Singleton pattern.

Whether multithreaded or not the pattern is supposed to maintain only Single object in one VM.

sanjeetja at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 23

> Don't understand why the basic pattern definition is being twisted?

A design pattern is not a perfect solution, using a design pattern is not an excuse to stand still, a pattern is the best practice as _currently_ understood and documented for the use of others. Patterns are not static things, they never have been, they change and evolve over time based on experience.

You should read Design Patterns... Gamma et.al. you will find the following two sentences in the second paragraph of the Preface.

Design Patterns capture solutions that have developed and evolved over time ... They reflect untold redesign and recoding as developers have struggled for greater reuse and flexibility in their software.

> I am horrified to read statements like

> "It depends on how you implement Singleton".

Why are you Horrified ? Horrified is a very strong word!

Are you horrified by semantic bugs ? Semantic bugs are everyday occurances in a lot of software not just implementation of the Singleton Pattern as was being discussed in this thread.The kicker with semantic bugs is that they are often only be bugs in a certain context. The Double Checked Locking idiom for example is a very common implementation of the singleton. However the discussion this thread exposes show that has problems in some contexts. Discussion and sharing of knowldege of correct and incorrect implementations is what extends the state of the art.

> If this so called 'version' of Singleton does not restrict

> object creation (for more than one instances) then it

> is not a Singleton pattern.

True, but which version and under context ?

These are very important points. The boundary conditions of a solution are just as important as the solution itself. The double checked locking idiom for example is only a problem in some contexts, multi-threaded in Java. However it offers other advantages that may be more important to the requirements. Lazy loading for example.Just because I've argued strongly against it's use in general. Doesn't mean it is not a perfectly acceptable solution in some contexts.

> Whether multithreaded or not the pattern is supposed

> to maintain only Single object in one VM.

In the beginning ...

There was the Singleton,

It came from the Gang Of Four,

it enforced singularity,

and the anointed ones did follow,

... and it was wondrous invention.

Then the anointed ones said ...

Thou shall use Lazy Loading,

it allows programs to load faster,

It came from the anointed ones and the programmers did follow

... and it was wonderous invention.

Then the anointed ones said ...

Thou shall not use Lazy Loading for it is unsafe.

Thou shall use Double Checked Locking,

It came from the anointed ones and the programmers did follow

... and it was wonderous invention.

Then the anointed ones said

Thou shall not use Double Checked for it is unsafe in a Multi-threaded envionment

Thou shall use static initialisation for that is always safe,

It came from the anointed ones and the programmers did follow,

... and it was wonderous invention.

But the people did cry and wail, for they had grown used to their fast loading programs,

so the anointed did invent many idiom for Singleton,

and some where good,

and some where bad,

and the programmers find it difficult.

So the anointed ones did teach all they knew of Singleton to the programmers,

And programmers did rejoice for their programs worked,

And the people did rejoice because their programs loaded fast,

And all could see that Singleton did wondrous things and were happy.

MartinS.a at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...
# 24

> Don't understand why the basic pattern definition is

> being twisted? I am horrified to read statements like

> "It depends on how you implement Singleton". If this

> so called 'version' of Singleton does not restrict

> object creation (for more than one instances) then it

> is not a Singleton pattern.

> Whether multithreaded or not the pattern is supposed

> to maintain only Single object in one VM.

You seem to not understand the discussion.

dubwaia at 2007-7-21 8:02:44 > top of Java-index,Other Topics,Patterns & OO Design...