Search code examples
javamultithreadingdesign-patternssingleton

Singleton & Multithreading in Java


What is the preferred way to work with Singleton class in multithreaded environment?

Suppose if I have 3 threads, and all of them try to access getInstance() method of singleton class at the same time -

  1. What would happen if no synchronization is maintained?
  2. Is it good practice to use synchronized getInstance() method or use synchronized block inside getInstance().

Please advise if there is any other way out.


Solution

  • The task is non-trivial in theory, given that you want to make it truly thread safe.

    A very nice paper on the matter is found @ IBM

    Just getting the singleton does not need any sync, since it's just a read. So, just synchronize the setting of the Sync would do. Unless two treads try to create the singleton at start up at the same time, then you need to make sure check if the instance is set twice (one outside and one inside the sync) to avoid resetting the instance in a worst case scenario.

    Then you might need to take into account how JIT (Just-in-time) compilers handle out-of-order writes. This code will be somewhat near the solution, although won't be 100% thread safe anyway:

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

    So, you should perhaps resort to something less lazy:

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

    Or, a bit more bloated, but a more flexible way is to avoid using static singletons and use an injection framework such as Spring to manage instantiation of "singleton-ish" objects (and you can configure lazy initialization).