Thursday, August 16, 2007

Singleton - One of a Kind Objects (Part II)

How will we tame the multi threading beast?
I'm a .Net developer having CLR as my run time. I never worked on Java, but C# and JAVA are almost similar. C# is advance form of JAVA and CLR is much more refine than JVM. Things that comes later are generally more advanced than things that came earlier. I was first introduced to this multi threading problem while going throgh Head First Design Patterns book. According to the book it was damn simple to fix this problem by making access to MySingleton.GetMySingletonInstance() synchronized. Code for this is simple as Singleton class itself,

using System;
using System.Runtime.CompilerServies;
internal sealed class MySingleton
{
//static variable to hold instance reference
private static MySingleton onlyInstance;
private MySingleton();
//Global i.e. public and static point of access
//No two treads may enter the method at the same time

[MethodImpl(MethodImplOptions.Synchronized)]
public static MySingleton GetMySingletonInstance()
{
if (onlyInstance==null)
{
onlyInstance=new MySingleton();
}
return onlyInstance;
}
}


This is as simple as it can get.We just decorated our method with MethodImpl attribute. This is available in System.Runtime.CompilerServices namespace. Now, no two threads can enter our GetMySingletonInstance() method at the same time. This solves the problem but leaves us with another headache, performance. We all know that this synchronization is only needed when onlyInstance is null i.e. we haven't yet created the MySingleton object. So adding synchronization lock to our method doesn't makes sense. Its just like solving one problem and creating another.


Now What?
There is a well known technique used to solve this problem. This is called Double Check Locking Technique. It's used when you want to have lazy instantiation i.e. you want your object to be constructed when your application first requests it. This is not a well known technique because its particularly interesting or useful. It's well known because a lot is written about it and a lot of Java developers use it. This was quite heavily used in Java but lately its discovered that this technique doesn't guarantee that it would work everywhere. If you want to know why this fails then just read through http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html. Just to show you how this double checking is implemented in C# I'll add some code here,

internal sealed class MySingleton
{
private static volatile MySingleton onlyInstance= null;
protected MySingleton() {}
public static MySingleton GetMySingletonInstance()
{
if (onlyInstance == null)
{
lock (typeof(MySingleton))
{
if (onlyInstance == null)
{
onlyInstance = new MySingleton();
}
}
}
return onlyInstance; }
}
What is the best implementation?
Use Type Initializer (static constructor) to create a simple and best implementation of singleton.
internal sealed class MySingleton
{
//Type constructor will be called when any member of type is accessed
//This initialization code will be added to Type Constructor by JIT compiler
private static MySingleton onlyInstance= new MySingleton();
private MySingleton() {}
public static MySingleton OnlyInstance
{
get { return onlyInstance;}
}
}
CLR automatically calls type's class constructor when the code attempts the access a member of the class. CLR ensures that calls to a type constructor are thread safe. Double check locking is less efficient than this technique as you need to create your own lock object and write all additional locking code yourself. Double check locking is interesting only if class has lots of members and you want to have your singleton constructed only when one of the member is called.

I hope! I answered my friend Pramod's question related to minimize overhead associated with double check locking technique.

No comments: