Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factory method to create singleton instance


I have written below code in static factory method to return single instance of DefaultCache.

public static ICache getInstance() {
   if (cacheInstance == null) {
      synchronized (ICache.class) {
         if (cacheInstance == null) {
            cacheInstance = new DefaultCache();
         }
      }
   }
   return cacheInstance;
}

Do we really need 2nd null check for cacheInstance inside the synchronized block?

like image 332
Sharad Ahire Avatar asked Dec 19 '12 15:12

Sharad Ahire


2 Answers

You need the second check as the value could have been set by another thread while you are trying to get the lock. In fact you don't have a safe view of this value until you are inside the synchronized block. It could have been set by another thread any amount of time ago.

The simplest lazy singleton is to use an enum

public enum DefaultCache implements ICache {
     INSTANCE
}

I assume you are not doing this so you can change the implementation.

BTW: I suggest you only use stateless singletons where possible and use dependanecy injection for all stateful objects as much as possible.

like image 190
Peter Lawrey Avatar answered Oct 02 '22 08:10

Peter Lawrey


I would avoid the need for the contention check using a lazily initialized singleton:

public class Singleton {
    public static ICache getInstance() {
       return LazyCacheInitializer.INSTANCE;
    }

    private class LazyCacheInitializer {
       private static final ICache INSTANCE = new DefaultCache();
    }
}
like image 30
Edwin Dalorzo Avatar answered Oct 02 '22 08:10

Edwin Dalorzo