• 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
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Question regarding Singleton pattern

 
Ranch Hand
Posts: 372
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In the double-checked locking implementation mentioned in Head First Design Patterns, I don't understand why the static variable holding the Singleton instance needs to be volatile. I think it would work fine, even if it is not volatile.

Can some one explain why this code needs the variable to be volatile? Also, I am not able to clearly understand why this code would work only in Java 5 and not previous versions

Here is the code from the book for the double-checked locking implementation of the Singleton pattern :

public Class Singleton
{
private static volatile Singleton uniqueInstance;

private Singleton(){}

public static Singleton getInstance()
{
if (uniqueInstance == null)
{
synchronized (Singleton.class)
{
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}

Why should uniqueInstance be volatile? What will happen if it's non-volatile?
and Why would this work only in Java 5?
 
Ranch Hand
Posts: 64
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Satish,

  • Each thread can have it's own copy of primitive as well reference identifiers which can be not in sync with other thread's set. Imagine following situation.


  • There are three threads A,B and C which are having reference of class Singleton. In their regular course of running, say thread A makes derefers Singleton reference, so in thread A's memory set, reference of class is null and as it's singleton class, same reference is referred by thread B and C. I know it's not practical, but we can't force JVM not doing this.

    Making reference uniqueInstance volatile will force JVM to update each individual thread's memory set to be in sync with eachother. And so above situation can be prevented. We can prevent using any null reference and inviting NullPointerException by checking its instance for NOT NULL condition before doing any thing critical.

  • Nothing will happen in regular java programs, this is specific to some critical situation only. I have not seen HFJava book so can't comment what will happen without seeing whole program.

  • I was able to compile and run the program in JDK1.4.




  • Ranchers, please correct me if i am wrong.

    Regards,
    Harshil
     
    author
    Posts: 14112
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    As this is very specific to multi-threading, I'm moving to Threads and Synchronization...
     
    Ranch Hand
    Posts: 1780
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Too complicated! 99%+ of the time, the following is sufficient, and nothing
    could be simpler:
    The less than 1% of the time this approach is bad is when Singleton has
    other static methods that should be callable, first, without causing the
    instance to be loaded.
     
    Sheriff
    Posts: 28321
    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 original code posted is an example of the "double-checked locking" problem. Google for that to find out more about it (the explanations you find will be far better than mine anyway). Maybe the problems it exposes in the Java memory model have been fixed in Java 5, but I don't know that for sure. Even if they have, I would still use the simple reliable version that Jeff posted.
     
    Ranch Hand
    Posts: 691
    Mac
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    may be this help you.
    http://cephas.net/blog/2003/02/17/using_the_volatile_keyword_in_java.html
     
    B.Sathish
    Ranch Hand
    Posts: 372
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks for the reply Jignesh. I think I understand now why that variable needs to be volatile. Looks like I have really understood volatile variables only now when reading about design patterns . If a thread uses an instance variable inside a synchronized block of code, then it has to update its private copy of the variable with the main copy before using it. Hence, if you are using instance variables inside the synchronized block, you do not need them to be volatile. You need them to be volatile only when you use them outside of the synchronized block. In this case, we are using uniqueInstance outside of the synchronized block and hence we need it to be volatile.

    By the way, Paul, that implementation that you would prefer to use is simple, but not reliable. It can violate the singleton pattern by creating 2 instances if 2 threads creep into the getInstance method at the same time. Hence you need to synchronize the method. Synchronizing the method would synchronize it every time it is called, but you need synchronization only for the first time the method is called when the uniqueInstance variable is null. Once the variable is initialized, you do not need synchronization any more, because no more instance creation is involved and this is where the double checked locking is handy because it applies synchronization only the first time providing significant performance improvement.
     
    Jeff Albertson
    Ranch Hand
    Posts: 1780
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by B Sathish:
    I think I understand now why that variable needs to be volatile. [...] You need them to be volatile only when you use them outside of the synchronized block.



    Careful: the following code is not valid -- why?

    Originally posted by B Sathish:

    By the way, Paul, that implementation that you would prefer to use is simple, but not reliable. It can violate the singleton pattern by creating 2 instances if 2 threads creep into the getInstance method at the same time. Hence you need to synchronize the method.



    That's false, because when a class is loaded, say when getInstance is first encountered, there is a kind of synchronizion going on in the class loading process that stops multiple threads from loading the same class or proceeding before the class is properly loaded. The code given works just fine, as would the following even easier implementation (if you don't mind using the public field...)
    Sometimes I like to write the most clever code I can, but perhaps the best thing to do is accept simpler is better. What's the old saying: if the code you write is as complex as you can make it, who are you going to get to debug it?!
     
    Jeff Albertson
    Ranch Hand
    Posts: 1780
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Errr... just to complete that last code example, make uniqueInstance final as well...
     
    B.Sathish
    Ranch Hand
    Posts: 372
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Jeff,
    I agree that this is thread-safe :

    public class Singleton {
    private static Singleton uniqueInstance = new Singleton();
    public static Singleton getInstance() {
    return uniqueInstance;
    }
    }

    What I meant was the classic implementation of the singleton pattern is not thread-safe

    public class Singleton
    {
    private static Singleton uniqueInstance;
    public static Singleton getInstance()
    {
    if (uniqueInstance == null)
    {
    uniqueInstance = new Singleton();
    }
    return uniqueInstance;
    }
    }

    The version that you have given is an example of an eagerly-created singleton instance. While it would be simple and thread-safe for most situations, it has the draw-back that it is resource-intensive as the instance is eagerly created. What if the Singleton instance is a highly resource-intensive object? and what if you cannot say for sure when the singleton instance would be used? and what if there is a chance that it would not be used at all? pre-loading this instance in memory would be a waste of resource right? That is when the classic implementation makes sense as it creates the instance lazily only when needed, but it is not thread-safe. You could make the method synchronized in the classic implementation, but that would apply synchronization every time the method is called . This is where the double-checked locking comes into picture, it applies synchronization only the first time and offers performance improvement and is thread-safe.

    Hence there are situations where you have to go for a more complex version. You cannot generalize that the simpler version will always work in every situation. Every implementation has its trade-offs. In this case it's resource-utilization Vs performance. Your version offers better performance and mine better resource utilization. You cannot blindly choose the simpler version, you need to evaluate these trade-off's, decide what's more important to you and then choose the right implementation
     
    Jeff Albertson
    Ranch Hand
    Posts: 1780
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by B Sathish:
    The version that you have given is an example of an eagerly-created singleton instance. While it would be simple and thread-safe for most situations, it has the draw-back that it is resource-intensive as the instance is eagerly created. What if the Singleton instance is a highly resource-intensive object? and what if you cannot say for sure when the singleton instance would be used? and what if there is a chance that it would not be used at all? pre-loading this instance in memory would be a waste of resource right? That is when the classic implementation makes sense as it creates the instance lazily only when needed, but it is not thread-safe.


    My take on this is that the simpler approach works 99+% of the time. I'm thinking of a Singleton class whose only public static method is getInstance. In this situation (which I've observed is the case in almost all well-written code) the only reason for mentioning the Singleton class in code is that you are about to use it! Hence there is no unnecessary pre-loading. If you can give me a realistic example to the contrary, I think forum members would be interested in seeing it.

    If you are worried about loading being too eager, there is another idiom that can come to the rescue, again based on class loading, not synchronization:(I may have flubbed that because I'm doing it from memory and have never had the need to use it.)
     
    You learn how to close your eyes and tell yourself "this just isn't really happening to me." Tiny ad:
    Gift giving made easy with the permaculture playing cards
    https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
    reply
      Bookmark Topic Watch Topic
    • New Topic