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

Getting Started with Stateless : A Lightweight Workflow Library Alternative for .NET

Image Credit: https://www.pioneerrx.com A year ago, I was looking for a simple workflow manager for a project I was working. Its a medium sized application that involves tracking the state of assets in the system. Back in 2008, Microsoft (MS) introduced new technologies along with the release of Visual Studio 2008: Windows Presentation Foundation (WPF), Windows Communication Foundation (WCF), and  Windows Workflow Foundation (WF). Having worked in a company utilizing mostly MS products for development, my first option was to go with WF. After doing some time reading and studying the library, I paused and decided it was too complex for my requirement. Using WF would be an overkill and the fact that it has, a rather, steep learning curve, there has to be another option. My mind toyed with the idea of developing a simple workflow library myself. It would be a learning experience but it might end up consuming a lot of time. Why reinvent the wheel? So I started querying the inte

Hiding Unwanted Python Folders and Files in Visual Studio Code

Visual Studio Code is a universal editor and pretty good at it. However, the explorer view maybe cluttered with the automatically generated folders and files confusing developers. Python is no different. Below are example files and folders generated by Python. The __pycache__ folder and *.pyc files  are totally unnecessary to the developer. To hide these files from the explorer view, we need to edit the settings.json for VSCode. Add the folder and the files as shown below: Copy and paste the lines below : "**/*.pyc" : { "when" : "$(basename).py" }, "**/__pycache__" : true

My First Blog for 2009

Im starting 2009 with a blog on foods. Since my 4 months voluntary exile in the US (hahaha), I started cooking ( full time! ) so Google is my cookbook and I am the chef ( sort of ). Yesterday , I was looking forward for another experiment on the kitchen lab (it gets messy sometimes) . What I have ? Pork belly , Chinese Okra , Squash . I was having doubts on whether the Chinese Okra is the same thing as the vegetable I know from the province , "kabatiti" . So after searching for "kabatiti" on the net , Google returned some informative links on some Ilocano Foods which made my day . Listed below are some Ilocano food worth mentioning . Abrao or Inabrao - assorted seasonal vegetables, typically malunggay, and that quintessentially Ilocano vegetable, saluyot, boiled in a bagoong and fish broth Ipon—tiny fish in season during the cold months Poki-Poki (also poqui-poqui), an innocent omelet made of eggplant sautéed with garlic, onions, tomatoes, and eggs Kabat