0

When need a singleton, is a static field a elegant solution?

class HelperSingleton {
  static Helper singleton = new Helper();

  public static Helper getInstance() {
       return singleton;
     }
  }

When two threads access to getInstance at the same time, is there a chance the field singleton is not initialized completely? Or see the default values for fields of the helper object, rather than the values set in the constructor? Static singleton is also lazy initialization?

I mean, static Helper singleton = new Helper(); is this assigment atomic? And won't return default values ?

znlyj
  • 1,109
  • 3
  • 14
  • 34
  • 1
    Shouldn't getInstance() be static ? – Marcello Romani May 15 '13 at 15:31
  • And there should be a private constructor. And `singleton` should be private and final. And ideally the class should be `final` too. – Jon Skeet May 15 '13 at 15:32
  • getInstance should be static, and your constructor should be private if you want to enforce a singleton. [ edit ] dangit @JonSkeet, you stole my answer, and you were faster than me :-p – Kevin Nelson May 15 '13 at 15:32
  • About Singleton classes and thread safety, this http://stackoverflow.com/questions/4115840/singleton-with-initializing-a-static-member question might be a useful read. – Marcello Romani May 15 '13 at 15:34

4 Answers4

1

I think that the most elegant solution for a singleton is this:

public enum Singleton {

    INSTANCE;

    public Singleton getInstance() {
        return INSTANCE;
    }
}

Using the singleton pattern is somewhat problematic because sometimes you don't know that you really only have just one of them. Consider the case for example when you are using class loaders.

This question (and others) has a thorough explanation by the way.

Community
  • 1
  • 1
Adam Arold
  • 29,285
  • 22
  • 112
  • 207
1

1) When a thread accesses static getInstance the first time class loader has to load the HelperSingleton class and it will lock other thread before class is loaded. So there is an implicit synchronization present. J.Bloch "Effective Java" Item 71 modern VM will synchronize field access only to initialize the class. Once the class is initialized, the VM will patch the code so that subsequent access to the field does not involve any testing or synchronization.

2) Your singleon is lazy, because there is only one access point - getInstance. Not only instance is created on demand but the whole class is loaded on demand. A class will not be initialized until it is used [JLS, 12.4.1].

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • Is there any official document about point 1 as you mentioned? – znlyj May 15 '13 at 15:44
  • [JLS 12.4.2](http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2) – AllTooSir May 15 '13 at 15:48
  • I think J.Bloch's Effective Java can be trusted, since the author led the design and implementation of many Java platform features. – Evgeniy Dorofeev May 15 '13 at 16:02
  • eh, is there any difference between static field singleton above and lazy initaialization holder class? – znlyj May 15 '13 at 16:04
  • If you had other static methods in your class you would need to wrap your instance in a holder to keep it lazy. Also, lazy is about something expensive to instantiate... – Evgeniy Dorofeev May 15 '13 at 16:44
0

Take a look at http://en.wikipedia.org/wiki/Singleton_pattern

There are a number of styles available explaining the good/bad.

jsurls
  • 365
  • 2
  • 11
0

If it were this :

class HelperSingleton {
  static Helper singleton = null;
  public static Helper getInstance() {
      if(singleton == null) {
         singleton = new Helper();
      }
      return singleton;
    }
}

There could be a possibility here :

  1. Thread 1 calls the getInstance() method and determines that singleton is null.

  2. Thread 1 enters the if block, but is preempted by Thread 2 before creating a new instance.

  3. Thread 2 calls the getInstance() method and determines that instance is null.

  4. Thread 2 enters the if block and creates a new Helper object and assigns the variable singleton to this new object.

  5. Thread 2 returns the Singleton object reference.

  6. Thread 2 is preempted by Thread 1.

  7. Thread 1 starts where it left off and executessingleton = new Helper(); which results in another Singleton object being created.

  8. Thread 1 returns this object.

So we end up with two instances. Best way to create Singletons are using enum as answered here.

static Helper singleton = new Helper(); 

Here a new instance of Helper is created when the class is loaded and singleton holds the reference to that instance. You can get the detailed initialization process in JLS 12.4.2.

Community
  • 1
  • 1
AllTooSir
  • 48,828
  • 16
  • 130
  • 164
  • Thank you, but I want to know is static Helper singleton = new Helper(); always return a completely initialized reference to a client? – znlyj May 15 '13 at 15:40