Design Patterns Revisited - Singletons, How Single They Are..
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!
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 :)
(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
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
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(){
}
}
Thomas Baldwin 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
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 ___ 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 ___ 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:
Next, take your application context and retrieve the singleton instance:
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+PatternsSingletons.aj:
public void instances_are_always_the_same() {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 ___ 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
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:
Christoph Kutzinski replied on Wed, 2008/07/30 - 10:47am
in response to:
Leszek Wasilewski
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:
Regards,
Slava Imeshev
Cacheonix: Distributed Java Cache