Saturday, November 26, 2005

Lazy Instantiation and the Singleton Pattern

Lazy Instantiation:

Lazy Instantiation lets the creation of objects be put off until they are actually needed i.e. they are created on need. Then what is its relation with singleton pattern. This is actuall what it is required in singleton pattern. Here I want to point out one more thing that lazy instantiation is closely related with the static members. The .Net compiler deals with the static members in the same way. They are created when any member (static or instance) member of the class is first referenced in the Application Domain and remain alived until the AppDomain exists but I think the big plus of using static members is that they are thread-safe and optimized by the constructor of .Net.

Usually we implement singleton-pattern using the following code:

public sealed class Singleton
{
static Singleton instance=null;

Singleton()
{ }

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

return instance;
}
}
}

but the above code is not thread-safe as two threads can simultaneously check the status of instance variable and both can enter into critical section. Another way of doing this is to use locking like :

public sealed class Singleton
{
static Singleton instance=null;

Singleton()
{ }

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

return instance;
}
}
}
}

but it will cause performace loss as at one time only one thread can be in critical section and having instance check outside the critical section will cause the same problem. A simple solution of the above problem is to declare and define the static instance of the object at the same time like:

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;
}
}
}

Now here a question arises. Why I have used static constructor when nothing is done in it? Well the secret of using it is 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. So to use static members in place of lazy instantiation, the class must have static constructor, otherwise ins laziness is not guaranteed.

Another thing, if the class has another static member, in that case also the laziness of the class is not guaranteed.

No comments: