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

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

Get Started with MongoDB Stitch : The New Backend As Service Offering from MongoDB

Halfway of this year, the guys from MongoDB launch their new backend as service product called MongoDB Stitch. While the launch is just for the beta, the promise of the service is quite interesting. MongoDB has been around for long now and some development stacks have been based on its database product, the MongoDB-ExpressJS-Angular-NodeJS (MEAN) and the MongoDB-ExpressJS-React-NodeJS (MERN) stacks to name a few. These stacks, however, relies on backend technology such as ExpressJS and NodeJS. The idea of provisioning servers and developing the backend solution makes it daunting for small to medium scale applications. MongoDB Atlas, at least made life much easier by providing on cloud database solution, but there must be a simpler solution, right? A solution the would stitch the backend and frontend together ( see what I did there ?).
MongoDB Stitch lets developers focus on building applications rather than on managing data manipulation code, service integration, or backend infrastruct…

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

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 internet for a better solution. I stumbled upon Stateless