Discussions

J2EE patterns: Revisiting Singleton Pattern

  1. Revisiting Singleton Pattern (23 messages)

    When we do lazy initialization in "getInstance()" method of Singleton class in that case we need to take care of multithreading. What happens if concurrent 5 threads try to get the instance of singleton class. Matter of fact if it is not properly synchronized it betrays the Singleton pattern implementation.
    Clip of code in "getInstance" can be below.

    if(singInst == null)
    {
      synchronized(Singleton.class)
      {

         if(singInst == null)
         {
             singInst = new Singleton();
         }

      }


    }

    Threaded Messages (23)

  2. Revisiting Singleton Pattern[ Go to top ]

    Pankaj,

    I'm not sure I understand what this post is supposed to be. I don't think it describes a design pattern (rather, a particular incorrect implementation of a design pattern). Also, I didn't understand from your post if the code you listed was supposed to be right or wrong. Anyway, it is wrong. It is an idiom called "double checked locking" which does not work under current Java Memory Model semantics. This issue is thoroughly discussed in:
    http://www.theserverside.com/patterns/thread.jsp?thread_id=13933&article_count=39

    Gal
  3. Revisiting Singleton Pattern[ Go to top ]

    also see my reply on
    http://www.theserverside.com/discussion/thread.jsp?thread_id=14327
  4. Revisiting Singleton Pattern[ Go to top ]

    I really appreciate your help. I went through the link u have provided. So it means that we have only two solutions to this problem
    1. Accept the synchronization of getInstance method.
    2. Or make instatiation in static field.
  5. Revisiting Singleton Pattern[ Go to top ]

    I believe that is the case
  6. Revisiting Singleton Pattern[ Go to top ]

    Moreover - I believe this implies that implementations of the String class are not fully thread safe. Scary.

    However in practice - I've never actually seen this problem in real life... so how likely it is happen in practice is a different matter.

    After reading the description of out-of-order writes I would guess that the likelihood of the problem occurring increases with the length of time taken to execute the constructor, and with the frequency of the threads accessing the getInstanceMethod(). So it may help to have minimal constructors for your objects (??).
  7. No need to worry[ Go to top ]

    Each thread calling synchronized getInstance() will block/wait till the lock is released by the previous thread and this one will release the lock after finishing from constructor side to write in main memory the attributes of the class instance.
    see

    http://java.sun.com/docs/books/jls/second_edition/html/memory.doc.html#28287
  8. No need to worry[ Go to top ]

    dac-
    i think you are off topic - we are well aware of how a java mutex is supposed to work.
    this thread is about the inherent problems in the Java memory model that make double checked locking a flawed approach.
    btw admins - this thread really belongs in the discussions area - could it be moved please.
    thanks
  9. No need to worry[ Go to top ]

    Tim,

    Why do you say that this version of double checked locking is flawed because of problems in the JMM? I agree that the JMM has problems, but I don't think these problems are necessarily the cause for this particular double-checked locking flaw. I think this version of double checked locking still won't work even under more reasonable semantics. You would have to at least declare the instance variable as volatile. Requiring complete linear ordering of all fields, even non-volatile ones, would probably be too harsh.

    Gal
  10. No need to worry[ Go to top ]

    Hi Gal-

    <gal>
    Why do you say that this version of double checked locking is flawed because of problems in the JMM?
    </gal>

    my understanding is that, according to the JMM, and considering the line:
    singInst = new Singleton();
    singInst can become non null _before_ the constructor has finished executing.
    hence a reference to only a partly initialised object can be returned (!!).
    i believe, in practice, modern JVMs actually don't have this behaviour, but the older ones do.
    the key point is that JVMs are not _required_ (according to the JMM) to set the reference to non null after the initialisation is complete - hence if we were to be absolutely safe and paranoid we should assume they never do.
    this would apply to all classes in the jvm, hence my comments about the String class (since String class maintains a static pool)
    having said that, in _practice_ I have never seen this, so I'm not too worried.
    moreover I believe declaring as volatile doesn't help matters for other reasons. (see ibm article).
    i think the bottom line is the double checked locking idiom isn't guaranteed to work, period. i don't know of any implementation that hasn't been shown to be flawed.
    hence the only safe thing to do is to use static member, or synchronize the entire method.
  11. No need to worry[ Go to top ]

    Hi Tim,

    <tim>
    my understanding is that, according to the JMM, and considering the line:
    singInst = new Singleton();
    singInst can become non null _before_ the constructor has finished executing. hence a reference to only a partly initialised object can be returned (!!).
    </tim>

    This is true, but I believe your description is slightly inaccurate. The thread will assign (JLS terminology) the singInst ref only after it runs the constructor. Assigning a field is a logical operation. There is still the question of when the thread will actually write the assigned value to the main memory. In multiple CPU cases, it is not so uncommon to have a thread update a local, in-CPU cache and flush it every once in a while instead of writing it directly to the main memory every time, as this is an expensive operation.
    Then there is the question of the reader thread. In just about every optimizing VM implementation, some fields are cached in the CPUs registers. More importantly, in multiple-CPU machines, each CPU may have it's own local copy of most of the data it works with - and it refreshes this copy every once in a while. Again, access to main memory is just too expensive. So unless you done something to require refreshing the cache (memory barrier), a reader thread may easily see cached values for the constructor-assigned data but a fresh value of the singInst reference.

    As a side note, in Java what causes these flushing of read/write caches is entering/leaving a synchronized block, respectively.

    To top this all off, there is the prescient write rule which is very important for some performance optimizations and allows a value to be written before it is assigned (under some restrictions, of course). This too can cause problems wihth the double-checked locking impl shown above.

    Non of the rules I listed above is an accidental consequence or a mistake. They are all important and practicaly necessary for any reasonable JVM implementation running multiple CPUs. What I ment by message above is that this specific double-checked locking implementation won't work under these rules. And because they are important and nobody is considering removing them, it wouldn't be fair to say this implementation is wrong because of flaws in the JMM. To summarize, I think everything you said in the quote was right except for the "!". What you described is normal behaviour in multiple CPU machines (unless some special precaution is taken to avoid the situation).

    You can see Pugh's page for a piece of code that *does* have this problem. I believe many JVMs have them. It simply requires a very specific coincidence, so you're unlikely to see it, and when you do you're unlikely to realize what you've seen, or be able to duplicate it.

    <tim>
    moreover I believe declaring as volatile doesn't help matters for other reasons.
    </tim>

    I did not mean it helps *now*. I ment, even under reasonable semantics, the double checked locking impl won't work unless you at least declare the singInst as volatile. As it happens, I believe according to the new JMM currently being developed, declaring singInst as volatile will fix the problem.

    <tim>
    i think the bottom line is the double checked locking idiom isn't guaranteed to work, period. i don't know of any implementation that hasn't been shown to be flawed.
    hence the only safe thing to do is to use static member, or synchronize the entire method.
    </tim>

    I completely agree. In the current JMM, with the loose rules on volatile, double checked locking is not an option. I do have one problem with what you said: you have to use a static member anyway. The question is whether to statically initialize it or lazily initialize it (with synchronization) :)

    Gal
  12. No need to worry[ Go to top ]

    I'd like to clarify that by "normal behaviour" I ment by the spec. The Alpha spec (and I believe also some of the Intel architectures) allow this reordering behaviour. In practice the occurences would be rare, but it can happen now, and may be more common in future hardware (particularly on Alpha).

    Gal
  13. The solution[ Go to top ]

    Interesting start of the discussion but then got carried away in the memory problems.

    Hope following link gives some insight into Singletons:

    http://developer.java.sun.com/developer/technicalArticles/Programming/singletons/

    --Lalit
  14. A little bit effort to understand ...[ Go to top ]

    sorry but my reply context was only for the question

    <
    So it may help to have minimal constructors for your objects (??).
    >

    containing a technical explanation for what the title says
    "No need to worry"
    so it seems you need more consistency when reading or maybe too much stress at the end-of-day and this makes you to be out-off-context ...

    _it_was_not about the "double checked locking idiom", because this topic was in use enough in my opinion last year for a long time and there
    where enough competent answers ...

    my regards,
  15. A little bit effort to understand ...[ Go to top ]

    Hi Dac-

    apologies for being blunt - but I am really not sure of the point you are trying to make...
    if you are making the point that a solution to the problem is to synchronize the entire method - then that is understood.
    although I'm sure you understand too the scaleability problems you introduce by doing such a thing make this solution less than ideal in many situations.
  16. Right[ Go to top ]

    Hi Tim,
    Exactly, is the only solution to be accepted. We deal with one imperfect jvm running on imperfect processors
    in one imperfect world, where to provide bad computer engineering is a business trend unfortunately.
    The problem is that managers which are contributing high to this imperfection will never listen to your
    details about scalability, and they will force you always to add bad design, bad engineering and to
    contribute to the glory of imperfect world ... As I argued with Gal last year the situation of a singleton
    class used as ServiceProvider by EJB's inside of one EJB container can be in my opinion more secure
    because of the container internal management of threads. In rest, think about consistency
    of your instance attributes and that's enough ... wait for the next versions of jvms ;-); maybe from marketing
    smart brains they will give birth to "new generation jvm" but I'm sure we all know what waits after to be
    discovered
    Best regards,
  17. Right[ Go to top ]

    Dac-

    I agree - the world is not perfect - we need to be practical about this.
    In this case I would tend to just implement the "flawed" double check locking anyway - and insist on using Sun JDM 1.2+ (which doesn't have the problem).
    That would be acceptable for my project, although probably not acceptable for all apps. (especially applets)
  18. ThreadLocal[ Go to top ]

    only those threads which synchronize will block.

    If the reference is not null, the thread will not block. The reference can be non-null before the constructor finished.

    making the function synchronized, using class loader lazyness are the most common and safe solutions.

    There is a actual solution which uses thread local storage, but this is complicated and nclear if it helps:

    http://www.javaworld.com/javaworld/jw-11-2001/jw-1116-dcl_p.html
  19. Hi,

    This is how we implement our singletons. It uses lazy initialisation, is thread safe and does not require the synchronized keyword. It is based on a construct in Effective Java (Item 48 - instance on demand holder).

    public class MySingleton{
        /**
         * Private constructor as part of the singleton pattern.
         */
        private MySingleton() {
        }

        /**
         * Singleton factory method.
         *
         * @return the one and only MySingleton.
         */
        public static MySingleton getInstance() {
            return MySingletonSingletonHolder.theInstance;
        }

        /**
         * Singleton implementation helper.
         */
        private static class MySingletonHolder {
            static final MySingleton theInstance = new MySingleton();
        }
    }
  20. The best way to avoid these pifalls will be use it like follows:
    Define the instance variable as follows:

    private static final PureSingelton _instance = new PureSingelton();

    Then a simple code for the getInstance() method.

    public static PureSingelton getInstance() {
        return _instance;
    }

    It will take most of the pain.

    Rajesh
  21. Revisiting Singelton pattern..[ Go to top ]

    Errmmm.... but this won't lazy initialize the singleton. The instance will be created when the class is first referenced, even if getInstance() is never called.

    I think the point of the original post was to encourage lazy initialization for expensive resources.
  22. The answer to the complete Thread is weill documented in the Book Effective Java by Joshua Bloch.

    The construct is as follows called the "initialize-on-demand holder class" idiom

    private static class FooHolder{
       static final Foo = new Foo();
    }

    public static Foo getFoo(){return FooHolder.foo;}

    The static will guarantee a thread safe singleton & the on demand/lazy class loading in Java will give you lazy initialization.

    The only catch is that the idiom works only for static fields.

    -Hrishi
  23. Hrishikesh,

    This solution has already been pointed out in this thread. However, as you mentioned, it only works for static fields that require lazy loading.
    I wonder if you can get something to work by dynamically generating classes with static fields at runtime... probably not. Does anybody have an idea?

    Gal
  24. Revisiting Singleton Pattern[ Go to top ]

    We can bypass the problem of thread synchronization in case of singleton instance creation by creating the instance at server start up time.