• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

threadsafety of a singleton

 
Ranch Hand
Posts: 84
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi,

I'm a little confused about the role static initialization played in threadsafety of a Singleton class.

a Singleton class like below seems to be working correctly without making the reference variable final.

public class Singleton {
private static Singleton s = new Singleton();

public Static Singleton getInstance() {
return s;
}
}

however, I saw lots of singleton examples in Effective Java look like below, with a final keyword
public class Singleton {
private static final Singleton s = new Singleton();

I heard some people say that static initialization use internal synchronization of classloader to ensure no race condition for the reference variable? is it true?
 
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The "final" attribute has nothing to do with synchronization; it simply tells the compiler that no other code is allowed to assign a new value to that variable.

Clearly that's an important design consideration for a singleton object. But since the variable is private, only code in the Singleton class could do that, and you can inspect the code to see that isn't the case.

However, synchronization aside, that code has a much more serious flaw for something that claims to be a "Singleton": it doesn't prevent anybody else from creating their own Singleton object.
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think Paul is implying that you should declare a private constructor for your class so it cannot be instantiated outside of your class.
 
Paul Clapham
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

D DeVice wrote:I think Paul is implying that you should declare a private constructor for your class so it cannot be instantiated outside of your class.



That's the usual solution that I have seen. There may be others for all I know, but since I don't need a singleton I haven't really followed the voluminous literature which has been produced about them.
 
Robert Strong
Ranch Hand
Posts: 84
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
yes, I do use private constructor.

but my question is that if the Singleton class is accessed by multiple threads, is it possible to have a race condition, that in the middle of static initialization, another thread calls getInstance() and thus return null? as no synchronization employed in getInstance() method to ensure timely visibility and atomicity.

 
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If your singleton has no constructor you will access it statically, like:
MyClass.getInstance(). Loading MyClass kicks off the static code blocks
and other member inits. They are run in order, from top to bottom. This
would include initializing the object to be returned by getInstance(). So
there can be no race condition because building the object to be returned
will complete before the return occurs. Does this help?

Jim ... ...
 
Robert Strong
Ranch Hand
Posts: 84
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jim,

yes, that helps.

So, when the classloader thread start loading the Singleton class, it also kick off static initialization, which is guaranteed to happen before the class is used.
 
Ranch Hand
Posts: 443
3
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's a really interesting question ;-)

The quick answer is final member initialisation does have special guarantees in the new Java Memory Model i.e. its not just about prohibiting reassignment in a multi threaded world, however it turns out the guarantees that static always provided are enough in this case ..


Ok so drilling into this in depth the question is ...
Have you prevented any data races and ensured visibility and with final static you have and the question is has the final achieved this for you.

Looking on the net there are a few goof confused blogs round this and I can see why.

final has special meaning under the new JMM (Java Memory Model) when used with member initialisation and multi threading, the question is it's visibility properties necessary given that its also declared static which also has some "interesting" properties with multi threading. Its important you pick up on the fact that final is not just about prohibiting new value assignment in a multi threaded world as if you use a non static final variable vs a non static final variable there is a obvious difference with multithreading.

See "How do final fields work under the new JMM? in the link below" ...
Java Memory Model

Next looking at static I can see where the confusion kicks in (the confusion would be round visibility not data races), there is indeed synchronization in the static initialisation of the class and always has been pre the JMM changes (so no data races) , you just need to confirm visibility, this you would assume given synchronisation is there but some documents don't make it clear e.g. Doug's JSR133 cookbook says ..

Static final initialization requires StoreStore barriers that are normally entailed in mechanics needed to obey Java class loading and initialization rules.



Which I first took to mean you need static final to get your memory barrier, however having looked at the java memory model documentation ...

The rules for class initialization ensure that any thread that reads a static field will be synchronized
with the static initialization of that class, which is the only place where static final fields can be
set. Thus, no special rules in the JMM are needed for static final fields.



So indeed in this particular case where multi threading is concerned final is giving you nothing, static is giving you already.


Again good question .

You might also want to look at ..
- How multiple class loaders can give you multiple singletons.
- How leaking the this reference or early access to final variables can cause issues with multithreading.

 
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Chris,

As per my nderstanding,

1) I think in context of thread safety final is used to make an object immutable.Also since final in new JMM has a changed meaning which says that if the variables of a class are final, then during the instantiation, all those varibles will get properly initialized value before the reference of that instance is made visible to other threads.

2) The internal Data Structure(which contains the constant pool) in the runtime area is thread safe, which is used by the classloader to load the class and create a .class instance. Now since Static initialization happens just after the class is loaded by the class loader and its .class instance is created in the heap, it remains questionable whether the assignment of appropriate values to static variables is thread safe or not.

Could someone throw some light on the same ?
 
Chris Hurst
Ranch Hand
Posts: 443
3
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I think in context of thread safety final is used to make an object immutable.



No, not really ..
First final doesn't make an object immutable, it makes its reference immutable, unless you mean make it immutable and then make any members similarly final. Java final isn't the same as C++ const and immutable is a dangerous word in multithreading, as an example String was always immutable but early java versions experienced an issue where they were not thread immutable i.e. they were immutable to any public interface but that does not mean thread immutable privately they mutated which was an issue.

Also since final in new JMM has a changed meaning which says that if the variables of a class are final, then during the instantiation, all those variables will get properly initialized value before the reference of that instance is made visible to other threads.



No.
First they will have been initialised but the result of any assignment may not be visible to any thread i.e. another thread may perceive them as if the actions of the first thread have not happened. Consider a class with non static member as part of the "no values out of thin air guarantee" this value is initialised to zero and then assigned to 6 , any subsequent assignment is prohibited. This assignment is guaranteed (new guarantee) to be visible to another thread when the constructor has completed, before that myconst could be observed to be zero by another thread . Think of it as the write of 6 may be cached which has to be released to main memory then the reading thread must invalidate its cache and pull the new value from memory if it helps. There is a visibility issue which is like an inability to guarantee invalidation of caches in this scenario (caches is not the only reason this can happen so strictly speaking we should talk in terms of "happens before ordering").

I suggest reading "Java Concurrency in Practice" for a better explanation, its a very hard topic to get explain with out dropping into formal language.

2) The internal Data Structure(which contains the constant pool) in the runtime area is thread safe, which is used by the classloader to load the class and create a .class instance. Now since Static initialization happens just after the class is loaded by the class loader and its .class instance is created in the heap, it remains questionable whether the assignment of appropriate values to static variables is thread safe or not.



The Java memory model says ...

The rules for class initialization ensure that any thread that reads a static field will be synchronized
with the static initialization of that class, which is the only place where static final fields can be
set. Thus, no special rules in the JMM are needed for static final fields.



We're discussing static final and there is no debate unless you believe I have not fully understood the quote from the Java Memory Model, any modern JVM that did not exhibit this behaviour as written would be bugged.

If you feel I may be miss interpreting some of your arguments I suggest you post this on the Java memory model discussion list where some of the guys behind the JMM subscribe , I'm always learning new stuff off there, though it is a bit techie.



 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic