Skip to main content

thread safe singleton and parametized threadstart

perhaps the most commonly discussed design pattern in OOP is singleton . just recently , we had a "design pattern" atmosphere in our office (some sort of an atmosphere relating to "resign patterns" lol) . singleton was in the limelight once again and one issue that made it more interesting is dealing with thread safe singleton . questions like : what is two or three threads starts at the same time and realizes that the singleton class is not yet existing , each of the threads will create a new instance of the singleton , thus breaking the main reason why singleton exist in the first place . i kinda got curious of all the solutions that was discussed so i made a little code to test it .

using the singleton design pattern allows the developer to work with only one instance of a class . this avoids the disadvantages of having too many instances of a single class in the memory together with the side effects it may cause in the application .

to start , i created a singleton class that is not threadsafe . creating a singleton class can be done simply by hiding the constructor from the outside by making it private and creating a static method to retrieve the instance . below is the my singleton class :
---------------------
class MySingleton
{
private static MySingleton _instance = null;
private string _instanceName = "Marvin";

public string InstanceName
{
get{ return _instanceName; }
}

private MySingleton(){}

//the GetInstance Method wthout parameter
public static MySingleton GetInstance()
{
if (_instance == null)
{
_instance = new MySingleton();
}
return _instance;
}

//the GetInstance Method with parameter
public static MySingleton GetInstance(string instanceName)
{
if (_instance == null)
{
_instance = new MySingleton();
_instance._instanceName = instanceName;
}
return _instance;
}
}
---------------------

to test it , i created a tester class with 2 methods to test the two GetInstance methods in my singleton
---------------------
static void Main(string[] args)
{
CreateInstance();
//test the other method
CreateInstanceWithParameter("Test");
Console.ReadKey();
}

static void CreateInstance()
{
//Test singleton without parameter
MySingleton singleton = MySingleton.GetInstance();
Console.WriteLine(singleton.InstanceName);
}

static void CreateInstanceWithParameter(object name)
{
MySingleton singleton = MySingleton.GetInstance((string)name);
Console.WriteLine(singleton.InstanceName);
}
---------------------
running the tester would prove that indeed our singleton works . it prints the instance that was first created which is the one having the name "Marvin" . the creation of another instance with a name "Test" failed .

some of you may ask , why make use of the type object in passing the parameter in the second method . it will all make sense when we will implement the singleton in multithreaded environment . to do these add the following code in your tester class and make sure that you reference System.Threading.
---------------------
static void CreateInstanceWithThreading()
{
ParameterizedThreadStart pts1 =
new ParameterizedThreadStart(CreateInstanceWithParameter);
ParameterizedThreadStart pts2 =
new ParameterizedThreadStart(CreateInstanceWithParameter);
ParameterizedThreadStart pts3 =
new ParameterizedThreadStart(CreateInstanceWithParameter);
ParameterizedThreadStart pts4 =
new ParameterizedThreadStart(CreateInstanceWithParameter);
ParameterizedThreadStart pts5 =
new ParameterizedThreadStart(CreateInstanceWithParameter);


Thread t1 = new Thread(pts1);
Thread t2 = new Thread(pts2);
Thread t3 = new Thread(pts3);
Thread t4 = new Thread(pts4);
Thread t5 = new Thread(pts5);

t1.Start("1");
t3.Start("3");
t4.Start("4");
t2.Start("2");
t5.Start("5");
}
---------------------
and update your CreateInstanceWithParameter method to
---------------------
static void CreateInstanceWithParameter(object name)
{
//Test singleton with parameter
MySingleton singleton = MySingleton.GetInstance((string)name);
string timeStamp = DateTime.Now.Millisecond.ToString();

Console.WriteLine("Time :" + timeStamp+" >> TID: "+name.ToString()+" IName: "+
singleton.InstanceName);
}
---------------------
the reason why i made the parameter type object is t support ParametizedThreadStart . this is a new concept in .net 2.0 that allows the thread to call a delegate with parameters . notice the way i called the Thread.Start() method , i passed the parameter needed by the delegate . the timestamp in the output will just give us an idea how the threads started . running the program may give different results . below are some of the results i received :
---------------------
run 1:
Time :0 >> TID: 3 IName: 3
Time :0 >> TID: 2 IName: 2
Time :0 >> TID: 1 IName: 2
Time :0 >> TID: 5 IName: 2
Time :0 >> TID: 4 IName: 2

run 2:
Time :203 >> TID: 3 IName: 3
Time :203 >> TID: 4 IName: 3
Time :203 >> TID: 1 IName: 1
Time :218 >> TID: 2 IName: 1
Time :234 >> TID: 5 IName: 1
---------------------
in run 1 , all the threads started at the same time and two instance of the singleton was created ( 3 and 2) . for the second run , 3 threads started at the same time and created two instance of the singleton (3 and 1) . in some cases only one instance is created . its hard to predict the operation . thus , we need to make the singleton threadsafe .

we can make use of locks or mutex to make sure that onlyone instance is created . by using these mechanishm we only allow a single thread to enter in the critical section at a time , thus , preventing two or more threads creating seperate instances of the singleton . shown below is the code to do it using lock and mutex
--------------------
//using lock:
//declare this
private static object _padlock=new object();

public static MySingleton GetInstance(string instanceName)
{
//lock the critical section
lock (_padlock)
{
if (_instance == null)
{
_instance = new MySingleton();
_instance._instanceName = instanceName;
}
}

return _instance;
}

--------------------
//using mutex
private static System.Threading.Mutex _mutex =
new System.Threading.Mutex();

//the GetInstance Method with parameter
public static MySingleton GetInstance(string instanceName)
{
_mutex.WaitOne();

if (_instance == null)
{
_instance = new MySingleton();
_instance._instanceName = instanceName;
}

_mutex.ReleaseMutex();

return _instance;
}
--------------------
run 1:

Time :343 >> TID: 3 IName: 1
Time :343 >> TID: 1 IName: 1
Time :375 >> TID: 2 IName: 1
Time :359 >> TID: 4 IName: 1
Time :375 >> TID: 5 IName: 1

run 2:
Time :984 >> TID: 1 IName: 1
Time :984 >> TID: 3 IName: 1
Time :15 >> TID: 4 IName: 1
Time :31 >> TID: 5 IName: 1
Time :15 >> TID: 2 IName: 1
--------------------
both the mutex and lock approach gurantees threadsafe singleton . run 1 simply illustrates how instance 1 got the lock to prevent instance 3 from creating another instance . run 2 demonstrates how instance 1 locked the critical section to prevent instance 3 from creating another instance .

there is however another way of making sure that only one instance is created . instantiate your singleton immediately to make sure that an instance is already running even if no one else is calling it . shown is the code to illustrate this point:
--------------------
class MySingleton
{
private static MySingleton _instance = new MySingleton();

private string _instanceName = "Marvin";

public string InstanceName
{
get
{
return _instanceName;
}
}

private MySingleton()
{
}

//the GetInstance Method wthout parameter
public static MySingleton GetInstance()
{
if (_instance == null)
{
_instance = new MySingleton();
}

return _instance;
}

//the GetInstance Method with parameter
public static MySingleton GetInstance(string instanceName)
{
if (_instance == null)
{
_instance = new MySingleton();
_instance._instanceName = instanceName;
}
return _instance;
}
}
--------------------
run 1:
Time :812 >> TID: 3 IName: Marvin
Time :812 >> TID: 4 IName: Marvin
Time :812 >> TID: 1 IName: Marvin
Time :843 >> TID: 5 IName: Marvin
Time :812 >> TID: 2 IName: Marvin
--------------------
the output illustrates that even if you call the method GetInstance with a parameter it will still retrun an instance bearing the default instance name "Marvin" . thus , the singleton is threadsafe .

take note that my reason of passing te instance name as a parameter is simply to put a better picture how the instances are created . all of the discussed ways above are acceptable , the choice depends on the developer .

Comments

Anonymous said…
Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!

Popular posts from this blog

renaming default namespaces for VSTO projects in VS2008

So here is the scenario , you are starting a VSTO project and decided that your default namespace is ExcelAddInTesterApp . You created the project and started coding the project. After several days , your boss called and said "hey marvin , make use of this namespace OurCompany.ExcelAddInTesterApp , we have to add our company name to it got it?" . You get back to your machine thinking its just a simple property just like any project you've been working on. So you right clicked the VSTO project and hit properties . Boom! What the F@#$? The default namespace textbox is disabled!!!!



I've been through this and I googled for ways to do it and ended up with a blog from a Microsoft MVP telling me it can't be done because it is disabled. Then I thought of Refactoring, the beauty and grandeur of the renaming process. I selected the namespace and hit the refactor menu hoping that this would solve the problem . Unfortunately , it did not rather it displayed the message box …

this year

.. i will learn new things, perhaps play a new instrument or go back to school.
.. i will find beauty on the open source community.
.. i will read more books and listen to more music.
.. i will pen more poems and possibly write more songs.
.. i will go for new distances and discover new terrains.
.. i will continue to pile running miles to stay fit and healthy.
.. i will strive to be free and make myself available to unknown future.
.. i will go out of my shell more often and be socially more open.

.. i will continue to grow and go with the changes of time.
.. i will be more patient and hopeful to things that may not even be possible.
.. i will be a better son, brother and more importantly a better father.
.. i will be closer with the great beyond.

.. i will continue to repair , refactor and upgrade myself to become a better version of me.

Farewell NU107.5

As I write this blog,  millions of Filipino rock fanatics may have already known what happens after 12:00 midnight tonight. The only surviving station that caters to the rock genre will, sadly, be closing down and permanently signing off tonight. The news came to late to enjoy every second of what is left.  The sad news came to me the last week of October.  Being a follower of the station, I never believed it at first. But online resources would say the station really is nearing its demise.  With several minutes to go, it will be dead air.