views:

737

answers:

9

I had another interview question. I thought this was silly, but maybe there is something I am missing. The question asked which GoF pattern this is (answer: singleton), and, if there are any problems, how I solve them.

I don't see any problems. I mentioned this is never freed and I expect that from this pattern. That is all I said. Am I missing something?

public class Class1
{
    private static Class1 oInstance = null;
    private Class1() { }
    public static Class1 GetInstance()
    {
        if (oInstance == null)
        {
            oInstance  = new Class1();
        }
        return oInstance ;
    }
}
+16  A: 

Thread-safety - multiple instances could be created if GetInstance() is called from competing threads.

Michael
+3  A: 

You have a potential race condition in multithreaded code. Two threads could each get past the null check before the constructor on the other thread is completed, so that both could end up constructing the class.

Drew Hoskins
+1  A: 

There is a potential issue with this if you have a multithreaded application. This can cause more than one instance to be constructed if two threads request at the same time.

I'd take a look at this page on Singletons in C#. It shows the problem in detail, as well as better options.

Reed Copsey
+13  A: 

See: An obvious singleton implementation for .NET?

There are multiple concerns you want to consider when implementing a Singleton pattern.

  • What happens when multiple callers request the singleton from multiple threads. It should just work.
  • When is the Singleton instance constructor called. You may want to defer it so it happens on the first call requesting the singleton, you may want it first instantiated at some other time.
  • Should people be able to inherit off your singleton class? What should the behavior be?
  • Should it be possible to switch your singleton instance to a different instance after the singleton has been instantiated. Answering yes to this violates the singleton pattern so in general the field holding singletons should be readonly.
  • API design, should you use a property or a method to return the Singleton instance.
  • Some people say singletons are evil. Should you even be considering it in the first place. This has been discussed quite often a good starting point is http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx

The following is a good general purpose pattern you could follow. Its thread safe, sealed, uses properties and defer instansiates the singleton.

public sealed class Singleton
{
    static class SingletonCreator
    {
        // This may seem odd: read about this at: http://www.yoda.arachsys.com/csharp/beforefieldinit.html
        static SingletonCreator() {}
        internal static readonly Singleton Instance = new Singleton();
    }

    public static Singleton Instance
    {
        get { return SingletonCreator.Instance; }
    }
}
Sam Saffron
+3  A: 

The code is not thread-safe. To make it so you need to do this:

public class Class1
{
    private static Class1 oInstance = null;
    private Class1() { }
    public static Class1 GetInstance()
    {
        if (oInstance == null)
        {
            lock(typeof(Class1))
            {
                if (oInstance == null)
                {
                    oInstance = new Class1();
                }
            }
        }
        return oInstance ;
    }
}

This is the most efficient way of lazily loading the instance as it only bothers to lock (can be expensive) when it is suspected the instance won't be instantiated for the next call. Checking again once in the lock ensures it will only be instantiated once.

Garry Shutler
+1 ...even though I would personally not use typeof(Class1) for locking, but rather just an object instance that is not used for anything else.
Fredrik Mörk
I am absolutly with Fredrik Mörk - locking a type object is really bad practice (as locking this is). Every code can dead lock you (even across appdomains) if you lock type objects (and every code that has access to an instance can dead lock you if you are locking this). lock (typeof(Class1)) { Class1.GetInstance(); } and you are in serious trouble ...
Daniel Brückner
Garry, see the pattern in my answer, its way cleaner IMHO
Sam Saffron
Funny, I looked up the advice on MSDN as lock() isn't something I use regularly and using typeof() in a static method is the recommended usage http://msdn.microsoft.com/en-us/library/aa664735(VS.71).aspx
Garry Shutler
A: 

so is the solution the following?

public class Class1
{
    private static Class1 oInstance = new Class1();
    private Class1() { }
    public static Class1 GetInstance()
    {
        return oInstance ;
    }
}
xeon
This is good but at the bare minimum oInstance should be readonly and it does not defer load the singleton ...
Sam Saffron
+5  A: 

Others mentioned thread safety. There's also the fact that they forgot to mark it as sealed, and so you could inherit from it and create multiple instances that way.

Joel Coehoorn
+1 I rolled up this concern into my answer
Sam Saffron
Doesn't the private default constructor prevent subclassing?
Andrew
@Andrew ... no it does not, try it yourself ...
Sam Saffron
A: 

Don't work at that company. The singleton pattern isn't a frequently used pattern and it's applicability in a pure OO system is questionable. Undoing a singleton pattern is a huge problem if you ever need to turn it back in to a normally constructed object.

That is a very broad statement. I think it depends on what type of development you do. My team writes system software in C++ and Java and Singletons are used HEAVILY in both.
xeon
It is a broad statement, however, in general these day I like chucking all my dependencies in a kernel of sorts which manages all these dependencies instead of having all my dependencies spread thin across my app. Having singletons makes testing much harder.
Sam Saffron
I thought this may be true as well, until I realized they were super useful on my current project...basically its a matter of instancing, sometimes you really just want one instance of your object and no more.
alchemical
Other things to consider with the singleton paradigm is that they can be bypassed by starting up another execution context. On the academic side singleton instances break the object oriented-ness of software. It's making an object out of a class, classes and objects are obviously not the same thing. The situation of static classes, static members, static variables, and singletons are akin to global variables.The academically "correct" in an OO sense way to make sure your entire program is using the same instance is to pass it through constructors.Pragmatically this needs to be weighed.
A: 

It's missing thread-safety, this page explains it really well.

alchemical