-J2EE Developer at Turkiye Is Bankası Core Banking Exchange project -Java-Flex Developer in TAV IT. Built softwares for several international airport (istanbul, ankara, izmir, tblisi, batumi, emfidha) with JPA/Spring/CXF/BlazeDS on server side and Flex on rich clients. -JavaEE&Process Project Laader at HSBC. -Presenter at Eclipsist 2008, on Rapid Rich Internet Application Development. Murat has posted 8 posts at DZone. View Full User Profile

Design Patterns Revisited - Singletons, How Single They Are..

07.25.2008
| 12418 views |
  • submit to reddit

I decided to write several posts about design patterns. Whether you use them or not, they are important and make your life easier (and probably increase your salary). Even if you are really not interested in design patterns, you will face questions about them in interviews or architectural design meetings. So you better open up your brain and learn some - there's nothing wrong with impressing a few colleagues.

The first pattern I will post is the Singleton Pattern. The mighty gof explains this pattern as follows; "Ensure a class only has one instance, and provide a global point of access to it.".
Simple isn't it, if you need only one instance of a resource, mostly because it would be expensive to create and hold new instances, you make sure there is only one unique living instance of that object. Singleton objects are God and if you don't want chaos, conspiracy and fighting like Olympian Gods than you must make sure you have only one!

Going back to basics how do we construct and instantiate an object? Just by using the constructor. Even when we don't write one, the compiler creates a default one for us. So to take control from the compiler we just create a default non-argument constructor and mark it as private. So we ensure no one would ever has access to it, to create a new instance(A). Next we type a public static method so whoever wants to use our object must use that entry point to access(B).
    public class SingletonObj {

private final static Singleton instance = new Singleton(); // our unique instance

private Singleton() {} //A

public static Singleton getInstance() { //B

return instance;

}

}
This is the most simple way to show a Singleton. You may also want to use a static initializer so our "instance" will be initialized only when it is first accessed.
public class SingletonObj {

private final static Singleton instance = null;

static {

instance = new Singleton(); // our unique instance

}

private Singleton() {} //A
 Or you might check if it is initialized in getInstance method.
public class SingletonObj {

private final static Singleton instance = null;

private Singleton() {} //A

public static Singleton getInstance() { //B

if (instance == null){

instance = new Singleton(); // our unique instance

}

return instance;

}

}
All of the examples above work quite the same and ensure the current running JVM has only one instance. Most experienced developers are now quite ready to leave a comment on how to hack this design. Ok, you can't just really ensure, but it is a hack and you must be expecting your colleagues not trying to break your design and mess up with resources :)Since the JVM lets us access even the private methods by reflection and once we get the methods it is possible to change the access rules and create new instances. Here is how to create more instances from a singleton;
    public class SingletonHack {

public static void main(String [] args);

Class clazz = Class.forName("SingletonObj"); //we load the class

Constructor[] cons = clazz.getDeclaredConstructors(); //get the constructors

cons[0].setAccessible(true); //change access rights

SingletonObj noMoreSingleton = (SingletonObj) cons[0].newInstance();

//we have brand new instance

}
 
Actually this is not something new and I'm quite sure most of you already knew it. Java is just like having Jedi powers. "The dark side of the force is a pathway to many abilities some considered to be unnatural". When you really need, it offers a dark side to make things work but you shouldn't be using those powers and staying on the light side. If you feel you need such a hack you must look back and try to find what did you do wrong and put yourself in Anakin's shoes :) 
Published at DZone with permission of its author, Murat Yener.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mauricio Garavaglia replied on Fri, 2008/07/25 - 9:37am

the third one is not thread safe :)

Mikael Grev replied on Fri, 2008/07/25 - 10:57am

public class SingletonObj

should be

public class Singleton

Alex Miller replied on Fri, 2008/07/25 - 11:06am

I wrote some more comprehensive posts on singleton (why it sucks) and double-checked locking (why it's broken and better ways to initialize singleton) that may be of interest.

As mgaravaglia noted, your third example is not thread-safe and should not be used.  The Initialize-On-Demand-Holder idiom is a better (and thread-safe) way to lazily initialize a singleton.

Darren Spurgeon replied on Fri, 2008/07/25 - 11:36am

I really like Bill Pugh's version, using the "Initialization on Demand Holder" idiom.

Slava Imeshev replied on Fri, 2008/07/25 - 4:39pm

 

I would say that the lazy initialization for an object that doesn't do much during the construction is an anti-patterns of its own:

1. No benefit is gained for added lines of code.

2. Prone to errors, just as we saw in the example where it immediately introduced a bug for a multithreaded environement.

So, the full initialization of the singngleton instance is a way to go for most cases.

Regards,

Slava Imeshev

Cacheonix: Clustered Java Cache 

Yves Zoundi replied on Fri, 2008/07/25 - 5:32pm

Another solution would be to use enum as Joshua Bloch suggests in his book(Effective Java).

enum Singleton{
/** single instance of this class */
INSTANCE;

/** a method */
public void doSomething(){

}
}

Tranquiliser Gt replied on Fri, 2008/07/25 - 8:06pm

Thread-safe version of the third one.

 

public class Singleton {  

private final static Singleton instance = null;

private Singleton() {}

public static Singleton getInstance() {

if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}

return instance;
}
}

 

Alex Miller replied on Fri, 2008/07/25 - 9:10pm

@tranquiliser: no no no no and no.  This is double-checked locking and it is NOT thread-safe. Without a memory barrier formed by synchronization on the read of instance, the instructions can be reordered and cause all sorts of thread problems.  The badness that can occur will become more and more likely as we add cores.  Do not do this.  For more detail, read Bill Pugh's paper on why double-checked locking is broken.

 

Murat Yener replied on Sat, 2008/07/26 - 2:32am in response to: Alex Miller

I respect the talk and corrections about the thread safe but this are example codes introducing the pattern and the concept else it is also meaningless to name the class as singleton. I prefer to give a simple non-thread safe  example to make people understand than give a complex one. May be next time I should just put a warning that this is not a code to go production without change...

Slava Imeshev replied on Sat, 2008/07/26 - 2:58am

 

Well, in your case you get a thread-safe code by declaring the getInstance() synchronized. That would turn your code into a useable example, no need for disclaimers.

 

Slava 

Sebastian Jancke replied on Sat, 2008/07/26 - 10:59am

And another - unneeded - post about singletons...

 

You know that Erich Gamma talked about "removing singleton" from the list of gof-patterns in a virtual new revision of his book? As singleton is not the concern of an object - but more of dependency and lifecycle configuration, one should use and dependency container and ensure singletoness there. Today, singleton cannot be regarded as a pattern anymore - as we have all experienced too much trouble with people using it. See also the excelent interview with Erich Gamma by Markus Völter (i think...) on se-radio.net: Both are also talking about this in the introductory part about DPs.

 

Sebastian

Slava Imeshev replied on Sat, 2008/07/26 - 2:46pm

Sebastian,

How would you demonstrate the implementation of the use case for singleton without the GoF's pattern? Any code samples?

Regards,

Slava Imeshev

Cacheonix: Distributed Java Cache

Peter Karussell replied on Sat, 2008/07/26 - 3:07pm in response to: Alex Miller

@alex yes, yes: it should work under java 1.5 and later!

see the paper you suggested. The only tiny thing you have to do is:

make the variable volatile so that all threads see the latest version...

Alex Miller replied on Sat, 2008/07/26 - 3:51pm

@Peter yes, *if* you wrote your code with volatile (which you didn't) and *if* you are using jdk 1.5+ (which many aren't) then it will work.  But I think it's simpler to just say, DO NOT USE DOUBLE-CHECKED LOCKING and leave it at that.  In all cases, it is less code, simpler code, equally as thread-safe, and possibly better performance to use the initialize-on-demand-holder idiom (see many references above) if you need to lazily instantiate a singleton. 

Josh Bloch recommends using an enum now to hold a singleton but I don't like this in all cases.  My main beef is that some singletons are written with mutable state and I think it's morally wrong :) to mutate state in an enum instance.  So, if you are registering and de-registering stuff in your singleton instance, then I object to holding it in an enum.  But then, I reject the use of the singleton pattern at all. :)

Peter Karussell replied on Sat, 2008/07/26 - 4:38pm in response to: Alex Miller

[quote](which you didn't)[/quote]

I am not tranquiliser

[quote] use the initialize-on-demand-holder idiom [/quote]

Yes, you are absolutely right. I just wanted to say that 'DO NOT USE DOUBLE-CHECKED LOCKING' is a bit too simple for me.

 

Sebastian Jancke replied on Sun, 2008/07/27 - 1:20am

@Slava,

take a Foo-object/component (whatever), and stress out:

- when singletons are useful

- why singleton is an anti pattern (today)

- why singletoness is not a concern of the object

- and thus: singletoness should be achieved by aspects or an di container (like spring)

 

for your sample, one could easily fire up a simple spring configuration, with <bean... singleton=true> and that's it code wise. Patterns are so much about concepts and less about code. Simple examples should be really sufficient. What's really important to other developers (and architects) are concepts, the "when" and some realworld usecases.

But that applies for all tutorials, blog posts and presentations: We have that many stuff out there, presenting yet another api for web/dataaccess/services/rest/.... But no one is really covering the hard part: What to choose, When to choos, What are real use cases, What are best practises, What are anti-patterns. That is information we really need and most authors are so ignorant of. It is really really hard work, much harder than writing another api-tutorial (which microsoft et al have been teaching us the last 20 years).

 

-Sebastian 

Slava Imeshev replied on Sun, 2008/07/27 - 2:14am in response to: Sebastian Jancke

Sebastian,

I have asked a pretty simple question which has been a request for code sample. Could you provide it or could you not?

 

Regards,

Slava Imeshev

 

Sebastian Jancke replied on Sun, 2008/07/27 - 3:31am

So,i've got a component, called Foo:

 

class Foo {
 private Foo() {..} //so ensure non-instantiatability (urgs, spelling) 
 ...
}

 

I want it to be a singleton, so fire up your spring config:

<bean id="foo" class="Foo" singleton="true"/> 

 

Next, take your application context and retrieve the singleton instance:

ApplicatonContext ctx; 
Foo alwaysTheSameInstance =  ctx.getBean("foo");

 

No cou can specifiy in your container, if you need singleton-per-thread, global singleton or instance per request (prototype mode, default). You can change that easily and of course, you can have more than one fully configured component of type "Foo", if you need (simply take another component's name). Of course this is not directly the singleton pattern, but that's not regarded as a pattern either.

 

 

Sebastian Jancke replied on Sun, 2008/07/27 - 4:13am

So how can we do it with aspects? Pretty simple:

 Again, we have our component Foo. Following is the needed aspect. One can do it in a more generic way, see Hannemann et al about DP implementations with AspectJ: http://hannemann.pbwiki.com/Design+Patterns

 

Singletons.aj:

import java.util.Hashtable;

public aspect SingletonProtocol {
    declare parents : Foo implements Singleton; //Declare singletoness
    pointcut subTypeExceptions(); //Exceptions from singletoness go here...

    private interface Singleton {};
    private Hashtable<Class, Object> singletons = new Hashtable<Class, Object>();

    Object around(): call(Singleton+.new(..)) && !subTypeExceptions(){                   
        Class singletonType = thisJoinPoint.getSignature().getDeclaringType();
       
        if (notInitialized(singletonType)) {
            singletons.put(singletonType, proceed());
        }
       
        return singletons.get(singletonType);
    }
   
    private boolean notInitialized(Class singleton) {
        return singletons.get(singleton) == null;
    }
}
 
My test: 
@Test
public void instances_are_always_the_same() {
    Foo foo1 = new Foo();
    Foo foo2 = new Foo();
    assertEquals(foo1, foo2);
}
 
What is missing:
It can be done with in an abstract, generic way (see Hannemann) - but this is just a simple example here. Also thread-safety is not ensured here!

Peter Karussell replied on Sun, 2008/07/27 - 3:03pm in response to: Alex Miller

Hi Alex,

I have one question about the initialize-on-demand-holder:

How can I lazy load an 'expensive' variable for several instances of the same class with this idiom?

For example you have

class Person {

List<Person> getDependencies() { /*expensive operation*/ return dependencies; }

}

Now I can have several instances of Person. It is easy with the dc-locking. But with the initialize-on-demand-holder idiom I see no way, because all instances will be forced to use the same variable for the 'dependencies'

Where is my mistake?

Peter.

Slava Imeshev replied on Sun, 2008/07/27 - 3:25pm in response to: Sebastian Jancke

How do you get context?

 

Slava 

Howard Lovatt replied on Sun, 2008/07/27 - 7:58pm

My pet project is a pattern enforcing compiler (PEC):

http://pec.dev.java.net/nonav/compile/index.html

You can use the compiler to enforce patterns and also write your own patterns and have the compiler enforce these. 

Christoph Kutzinski replied on Mon, 2008/07/28 - 4:43am

How are the first and second example different?

AFAIK, in both cases the singleton is only created the first time you access the class. If you wanted to demonstrate creation on demand you should use the - already mentioned - "Initialization on Demand Holder" idiom.

Sebastian Jancke replied on Mon, 2008/07/28 - 5:23am in response to: Slava Imeshev

[quote=imeshev]

How do you get context?[/quote]

Slava, as you would normaly in Spring framework: create from xml-config or by hard-coded configuration (object definition builder, etc...). That's not topic of this blog-entry and it's spring basics - so it's up to you to learn on spring if you want to know. As DI containers are pretty common and required for todays architectures, it's worth the price to learn. You should be able to learn the basics in a couple of hours. Spring is (in it's most basic form) very simple.

 

-Sebastian

Slava Imeshev replied on Mon, 2008/07/28 - 2:36pm in response to: Sebastian Jancke

[quote=sebastian jancke] That's not topic of this blog-entry and it's spring basics - so it's up to you to learn on spring if you want to know. As DI containers are pretty common and required for todays architectures, it's worth the price to learn. You should be able to learn the basics in a couple of hours. Spring is (in it's most basic form) very simple.[/quote]

I am quite familiar with Spring, and it has its place. That's why I asked you to show the actual effort of not having a singleton. What I just have shown that the idea of adding a DI framework, a bunch of XML files and a complicated object creating scheme just to avoid singleton seems odd.

Slava

Edmund Fong replied on Wed, 2008/07/30 - 4:46am

Double-checked locking and the Singleton pattern

http://www.ibm.com/developerworks/java/library/j-dcl.html

Summary

In an effort to avoid costly synchronization in singletons, programmers, quite ingeniously, invented the double-checked locking idiom. Unfortunately, it was not until this idiom was in fairly wide use that it became apparent that it is not a safe programming construct due to the current memory model. Work is underway to redefine areas of the memory model that are weak. However, even under the newly proposed memory model, double-checked locking will not work. The best solution to this problem is to accept synchronization or use a static field.

Manjuka Soysa replied on Wed, 2008/07/30 - 6:00am in response to: Slava Imeshev

So in the end you need something like a Singleton to get a handle on the Context.. enjoyed your reasoning Slava :-)

 

Leszek Wasilewski replied on Wed, 2008/07/30 - 10:13am in response to: Mauricio Garavaglia

[quote=mgaravaglia]the third one is not thread safe :)[/quote]

 You might be interested in this: http://www.ibm.com/developerworks/java/library/j-dcl.html

Double check locking idiom and problems associated with it! 

In general: if you think that this is thread-safe implementation of Singleton (and you must admit this is not the simplest one which can be met), you are wrong:

public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}

 

Christoph Kutzinski replied on Wed, 2008/07/30 - 10:47am in response to: Leszek Wasilewski

In general: if you think that this is thread-safe implementation of Singleton (and you must admit this is not the simplestI one which can be met), you are wrong:

 

Not if instance is volatile and you running under Java >= 5 ;-)

But seriously, to avoid such confusion, one should better rely on static initialization or (if lazy init is really needed) the Initialize on Demand Holder idiom.

 

Slava Imeshev replied on Wed, 2008/07/30 - 11:35am

We have to put pure double-checked locking to rest, really.

The simplest and the cheapest is just to declare getInstance synchronized instead of messing with double locking. The speed difference is negligible. I have run the following code and got 7s for 10,000,000 accesses for not synchronized (not safe but fastest) method and 9s for the safe synchronized. The difference is only 0.2mks/call:

 

   private static final int NUMBER_OF_GET_INSTANCE = 10000000;
private static final int NUMBER_OF_THREADS =
Runtime.getRuntime().availableProcessors();

public static class Singleton {

private static Singleton INSTANCE = null;
private int counter = 0;

private Singleton() {
}

public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}

public int getCounter() {
return counter;
}

public synchronized void incrementCounter() {
counter++;
}
}


/**
*/
public void testSingletonSpeed() throws InterruptedException {
final long started = System.currentTimeMillis();
final CountDownLatch startLatch = new CountDownLatch(1);
final Thread[] threads = new Thread[NUMBER_OF_THREADS];
for (int i = 0; i < NUMBER_OF_THREADS; i++) {
final Thread th = makeAccessThread(startLatch,
NUMBER_OF_GET_INSTANCE);
threads[i] = th;
th.start();
}
startLatch.countDown();
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
final long totalTimeMillis = System.currentTimeMillis() - started;
log.debug("time, ms: " + totalTimeMillis);
log.debug("counter: " + Singleton.getInstance().getCounter());
}


private Thread makeAccessThread(final CountDownLatch startLatch,
final int numberOfGetInstance) {
return threadFactory.newThread(new Runnable() {
public void run() {
try {
startLatch.await();
for (int j = 0; j < numberOfGetInstance; j++) {
Singleton.getInstance().incrementCounter();
}
} catch (InterruptedException e) {
return;
}
}
});
}

Regards,

Slava Imeshev

Cacheonix: Distributed Java Cache

 

 

 

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.