Double Checked Locking

Discussions

Performance and scalability: Double Checked Locking

  1. Double Checked Locking (4 messages)

    I discovered a pattern i was using, that is not correct:

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

    ... to avoid synchronization (=slow) when the singleton exists (= most of the cases).

    This is NOT GOOD, it does not work!

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

    I wonder, if this usage below is also NOT correct: i have a singleton factory method that hold a Map (ContextMap.vm is just a Map) of named singletons.
    I believe this usage is ok, but after i read about the previous article, i'm in doubt.

    public static Object singleton(Object name,Transform factory,Object args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, java.lang.reflect.InvocationTargetException, Exception
        {
            Object object = ContextMap.vm.get(name);
            if (object == null)
            {
                synchronized(ContextMap.vm)
                {
                    object = ContextMap.vm.get(name);
                    if (object == null)
                    {
                        object = factory.transform(args);
                        ContextMap.vm.put(name,object);
                    }
                }
            }
            return object;
        }
        
    Any idea's on this?

    Threaded Messages (4)

  2. Double Checked Locking[ Go to top ]

    Hi -
    it looks like your second example will have the same problems as the first.
    solution 1 would be to acquire the mutex before the test of = null.
    you can do this by making the method synchronized, or putting the synchronized(object) block before the test - they will produce the same code.
    as you mentioned there is a slight performance hit by doing this.
    in my experience the performance hit is not *that* big, but if it is very important in your system, you could consider creating the singleton instance in a static initializer - by doing so, you will ensure the object is never null in the getter method, and you won't require the mutex.

    eg.
    public class Singleton
    {



  3. Double Checked Locking[ Go to top ]

    Ooops! I pressed submit to soon!
    Here is the rest of the message:

    Hi -
    it looks like your second example will have the same problems as the first.
    solution 1 would be to acquire the mutex before the test of = null.
    you can do this by making the method synchronized, or putting the synchronized(object) block before the test - they will produce the same code.
    as you mentioned there is a slight performance hit by doing this.
    in my experience the performance hit is not *that* big, but if it is very important in your system, you could consider creating the singleton instance in a static initializer - by doing so, you will ensure the object is never null in the getter method, and you won't require the mutex.

    I think this should work:

    eg.
    public class Singleton
    {
      private static Singleton _instance;
      static
      {
        init();
      }
      private static synchronized init()
      {
        if (_instance == null)
        {
          _instance = new Singleton();
        }
      }
      public static Singleton getInstance()
      {
        return _instance;
      }
    }

    You may not need to test for instance == null in the init() method, or synchronize it but I've put it in just in case, it could get called more than once, I can't remember if that's possible off the top of my head - if in doubt I'd check the Java language specification.
    (I imagine it would be called the first time the class is instantiated, per classloader).

    Hope that helps


  4. Double Checked Locking[ Go to top ]

    no! i don't understand why my solution is not good: since ContextMap.vm.get(name) is a method invocation, it will be executed once outside and once inside the synchronized block. I don't see where this can suffer from the problem with double checked locking. I can not imagine an optimizing compiler that translates this into code that is not equivalent to what i intended to do, because it does have to call the method twice, and the second call is inside synchronization. What's the problem?
  5. Double Checked Locking[ Go to top ]

    This article should shed some light onto why your method still does not work.

    http://www-106.ibm.com/developerworks/java/library/j-dcl.html?dwzone=java