0

I am basically looking for a caching mechanism for the users of HelperWrapper. Is this a correct use of double checked singleton?

final class HelperWrapper {
  private static volatile Helper helper = null;
 
  public static Helper getHelper() {
    if (helper == null) {
      synchronized (HelperWrapper.class) {
        if (helper == null) {
          helper = new Helper();
        }
      }
    }
    return helper;
  }
}

I know this wouldn't prevent someone from instantiating their own Helper objects, but that isn't the goal.

Additional info:

  • I cannot modify the Helper class to make the constructor private. Nor do I want to.
  • The requirements dictate that the helper should not be eagerly instantiated
Ares
  • 1,411
  • 1
  • 19
  • 35
  • Related reading: [Item 3 from Effective Java](http://www.informit.com/articles/article.aspx?p=1216151&seqNum=3) – JonK Apr 27 '15 at 14:48
  • I cannot modify Helper's source code, hence I cannot make its constructor private. I'm not trying to prevent others for instantiating their own Helper. – Ares Apr 27 '15 at 14:51
  • @VinceEmigh Double checked locking is no longer broken since Java 5. – Chetan Kinger Apr 27 '15 at 14:58
  • @Ares You can't modify `Helper` in any way? If that's the case, are you using a DI framework such as `Spring` or `Guice` in your applicaiton? If yes, you could enforce singleton without modifying `Helper` at all. – Chetan Kinger Apr 27 '15 at 15:01
  • please look at : [enum as singlton](http://stackoverflow.com/questions/26285520/implementing-singleton-as-enum-in-java) this is better. – igreenfield Apr 27 '15 at 17:04
  • https://stackoverflow.com/questions/7855700/why-is-volatile-used-in-this-example-of-double-checked-locking/ – Ravindra babu May 30 '17 at 11:39

1 Answers1

2

As of Java 5, that implementation is safe. However, consider using an internal class instead:

final class HelperWrapper {
  private static final class DeferredLoader {
    public static final Helper HELPER_INSTANCE = new Helper();
  } 

  public static Helper getHelper() {
    return DeferredLoader.HELPER_INSTANCE;
  }
}

This both provides thread-safety and lazy initialization while leveraging the thread safety guarantees of class initialization to avoid volatile or synchronization keywords on a per call basis.

Community
  • 1
  • 1
Brett Okken
  • 6,210
  • 1
  • 19
  • 25
  • I still don't understand what's the point of a Singleton wrapper when Helper does not have a private constructor? – Chetan Kinger Apr 27 '15 at 15:46
  • I cannot speak for @Ares. It could simply be that a 3rd party provides `Helper` and @Ares has found they want to consume as a singleton (perhaps for performance reasons). You are correct that they cannot prevent direct instantiation. – Brett Okken Apr 27 '15 at 15:53
  • @bot There are a number of cases where you want a singleton instance of some type of object in a given context even though it does not have to be a singleton for the entire vm. For example, if a class can leverage an ExecutorService, it may want that to enforce a single object for that class. That does not mean that no one else in jvm should be able to produce an instance. – Brett Okken Apr 27 '15 at 15:54
  • Do you think it would make sense to add a `static` factory method called `newInstance` to the wrapper? I know this won't change much but it will atleast give an option to rely completely on the wrapper to get hold of a `Helper` – Chetan Kinger Apr 27 '15 at 16:52