Senator Guerra Souty original series calendar,replica hublot blue steel peach pointer collocation of rolex replica Rome digital scale, track type minute replica watches scale shows that the classical model is swiss replica watches incomparable, wearing elegant dress highlights.
mr-ponna.com

 

YOU ARE HERE: HOME Articles Implementing the Singleton Pattern in NET



Implementing the Singleton Pattern in .NET

View(s): 6173


Implementing the Singleton Pattern in .NET

The intent of the Singleton pattern as defined in Design Patterns is to "ensure a class has only one instance, and provide a global point of access to it".

What problem does this solve, or put another way, what is our motivation to use it? In nearly every application, there is a need to have an area from which to globally access and maintain some type of data. There are also cases in object-oriented (OO) systems where there should be only one class, or a predefined number of instances of a class, running at any given time. For example, when a class is being used to maintain an incremental counter, the simple counter class needs to keep track of an integer value that is being used in multiple areas of an application. The class needs to be able to increment this counter as well as return the current value. For this situation, the desired class behavior would be to have exactly one instance of a class that maintains the integer and nothing more.

At first glance, one might be tempted to create an instance of a counter class as a just a static global variable. This is a common technique but really only solves part of the problem; it solves the problem of global accessibility, but does nothing to ensure that there is only one instance of the class running at any given time. The responsibility of having only one instance of the class should fall on the class itself and not on the user of the class. The users of the class should always be free from having to monitor and control the number of running instances of the class.

What is needed is a way to control how class instances are created and then ensure that only one gets created at any given time. This would give us exactly the behavior we require and free a client from having to know any class details.

Logical Model

The model for a singleton is very straightforward. There is (usually) only one singleton instance. Clients access the singleton instance through one well-known access point. The client in this case is an object that needs access to a sole instance of a singleton. Figure 1 shows this relationship graphically.

Ee817670.singletondespatt01(en-us,PandP.10).gif
Figure 1. Singleton pattern logical model

First version - not thread-safe

// Bad code! Do not use!
public sealed class Singleton
{
    static Singleton instance = null;
 
    Singleton()
    {
    }

    
public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

As hinted at before, the above is not thread-safe. Two different threads could both have evaluated the test if (instance==null) and found it to be true, then both create instances, which violates the singleton pattern. Note that in fact the instance may already have been created before the expression is evaluated, but the memory model doesn't guarantee that the new value of instance will be seen by other threads unless suitable memory barriers have been passed

Second version - simple thread-safety

public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object padlock = new object();

    
Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

This implementation is thread-safe. The thread takes out a lock on a shared object, and then checks whether or not the instance has been created before creating the instance. This takes care of the memory barrier issue (as locking makes sure that all reads occur logically after the lock acquire, and unlocking makes sure that all writes occur logically before the lock release) and ensures that only one thread will create an instance (as only one thread can be in that part of the code at a time - by the time the second thread enters it,the first thread will have created the instance, so the expression will evaluate to false). Unfortunately, performance suffers as a lock is acquired every time the instance is requested.

Note that instead of locking on typeof(Singleton) as some versions of this implementation do, I lock on the value of a static variable which is private to the class. Locking on objects which other classes can access and lock on (such as the type) risks performance issues and even deadlocks. This is a general style preference of mine - wherever possible, only lock on objects specifically created for the purpose of locking, or which document that they are to be locked on for specific purposes (e.g. for waiting/pulsing a queue). Usually such objects should be private to the class they are used in. This helps to make writing thread-safe applications significantly easier.

Third version - attempted thread-safety using double-check locking

// Bad code! Do not use!
public sealed class Singleton

{
    static Singleton instance = null;
    static readonly object padlock = new object();

    
Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}

This implementation attempts to be thread-safe without the necessity of taking out a lock every time. Unfortunately, there are four downsides to the pattern:

  • It doesn't work in Java. This may seem an odd thing to comment on, but it's worth knowing if you ever need the singleton pattern in Java, and C# programmers may well also be Java programmers. The Java memory model doesn't ensure that the constructor completes before the reference to the new object is assigned to instance. The Java memory model underwent a reworking for version 1.5, but double-check locking is still broken after this without a volatile variable (as in C#).
  • Without any memory barriers, it's broken in the ECMA CLI specification too. It's possible that under the .NET 2.0 memory model (which is stronger than the ECMA spec) it's safe, but I'd rather not rely on those stronger semantics, especially if there's any doubt as to the safety. Making the instance variable volatile can make it work, as would explicit memory barrier calls, although in the latter case even experts can't agree exactly which barriers are required. I tend to try to avoid situations where experts don't agree what's right and what's wrong!
  • It's easy to get wrong. The pattern needs to be pretty much exactly as above - any significant changes are likely to impact either performance or correctness.
  • It still doesn't perform as well as the later implementations

Fourth version - not quite as lazy, but thread-safe without using locks

public sealed class Singleton
{
    static readonly Singleton instance = new Singleton();

    
// Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

As you can see, this is really is extremely simple - but why is it thread-safe and how lazy is it? Well, static constructors in C# are specified to execute only when an instance of the class is created or a static member is referenced, and to execute only once per AppDomain. Given that this check for the type being newly constructed needs to be executed whatever else happens, it will be faster than adding extra checking as in the previous examples. There are a couple of wrinkles, however:

  • It's not as lazy as the other implementations. In particular, if you have static members other than Instance, the first reference to those members will involve creating the instance. This is corrected in the next implementation.
  • There are complications if one static constructor invokes another which invokes the first again. Look in the .NET specifications (currently section 9.5.3 of partition II) for more details about the exact nature of type initializers - they're unlikely to bite you, but it's worth being aware of the consequences of static constructors which refer to each other in a cycle.
  • The laziness of type initializers is only guaranteed by .NET when the type isn't marked with a special flag called beforefieldinit. Unfortunately, the C# compiler (as provided in the .NET 1.1 runtime, at least) marks all types which don't have a static constructor (i.e. a block which looks like a constructor but is marked static) as beforefieldinit.

One shortcut you can take with this implementation (and only this one) is to just make instance a public static readonly variable, and get rid of the property entirely. This makes the basic skeleton code absolutely tiny! Many people, however, prefer to have a property in case further action is needed in future, and JIT inlining is likely to make the performance identical. (Note that the static constructor itself is still required if you require laziness.)

Fifth version - fully lazy instantiation

public sealed class Singleton
{
    Singleton()
    {
    }

    
public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

Here, instantiation is triggered by the first reference to the static member of the nested class, which only occurs in Instance. This means the implementation is fully lazy, but has all the performance benefits of the previous ones. Note that although nested classes have access to the enclosing class's private members, the reverse is not true, hence the need for instance to be internal here. That doesn't raise any other problems, though, as the class itself is private. The code is a bit more complicated in order to make the instantiation lazy.



  Last updated on Saturday, 01 February 2014
  Author: rajeeva.nagarakanti
3/5 stars (4 vote(s))

Register Login Ask Us Write to Us Help