Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double checked locking in modern JVMs

I have a class that might throw any run-time exceptions during initialization. I want the class to be a singleton since the cost of keeping several objects in memory is high. I am using that class in another class.

My use case is as follows:

  • I have to use a single instance of Controller.
  • Each instance of Parent must use the same Controller instance.
  • Controller constructor might throw exceptions.
  • If instantiation fails, I should retry to instantiate after sometime.

So I check if my Controller instance is null when I try to do a "get" on the Controller, if yes, I try to instantiate it again.

Following is my code:

class Parent
{
    private static volatile Controller controller;
    private static final Object lock = new Object();

    static
    {
        try
        {
            controller = new Controller();
        }
        catch(Exception ex)
        {
            controller = null;
        }
    }

    private Controller getController() throws ControllerInstantiationException
    {
        if(controller == null)
        {
            synchronized(lock)
            {
                if(controller == null)
                {
                    try
                    {
                        controller = new Controller();
                    }
                    catch(Exception ex)
                    {
                        controller = null;
                        throw new ControllerInstatntationException(ex);
                    }
                }
            }
        }
        return controller;
    }

    //other methods that uses getController() 
}

My question is, is this code broken? I read somewhere that the above code would be a problem in JVM 1.4 or earlier. Can you provide references/solutions? Please note that I am asking this question because there is a lot of confusion regarding this topic in the internet.

Thanks.

like image 670
Swaranga Sarma Avatar asked Feb 22 '23 11:02

Swaranga Sarma


2 Answers

I believe it's not broken, cause of volatile declaration. But imho better to avoid code like this. There is no guarantee, that this code will work with Java 8 for example. There are another way to create lazy singleton. I always (almost) use this method. First time faced with it in Java Concurrency in Practice book.

public class Singleton {
        private Singleton() { }

        private static class SingletonHolder { 
                public static final Singleton instance = new Singleton();
        }

        public static Singleton getInstance() {
                return SingletonHolder.instance;
        }
}

I don't know what you are doing in your code, it's hard to say, how to tweak it. The most straightforward way, simply use synchronize method. Do you seriously want to receive some performance benefit using double-check-locking ? Is there bottle-neck in synch method ?

like image 182
Anton Avatar answered Mar 09 '23 01:03

Anton


The only thing which is broken is to make the example far more complicated than it needs to be.

All you need is an enum

// a simple lazy loaded, thread safe singleton.
enum Controller {
    INSTANCE
}
like image 22
Peter Lawrey Avatar answered Mar 09 '23 00:03

Peter Lawrey