Skip to main content

Knowing Singelton

Singelton pattern in one of the most commonly used and talked about design pattern. Many appreciates it usefulness and many advocate against it. In this post we are not going to discuss all that but will concentrate on its implementation in c#.

Type:
It is a creational design pattern.

Intent:
It ensures that only one instance of the class exists.

Usage:
It is generally used when only one instance of a class is required. Thus, it can be seen to be used in logging frameworks, configuration objects etc.

The ownership of instance creation lies with the class itself. This is because we can not ensure that only one instance will ever exists for the class if the responsibility lies with someone else.

The class will instantiate the object when it will be used for the first time. This also ensures lazy initialization.

Point to consider:
Singelton object is mostly made accessible globally and thus being abused by being used as global variable. We must keep in mind that not only the singelton object but the whole object graph associated to it (which can be traversed through it) becomes global. Though most of us will say no to using global variables but will readily say yes to singeltons.

Simple Implementation:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlayingWithSingelton
{
    public class SimpleSingelton
    {
        private static SimpleSingelton _instance;

        private SimpleSingelton()
        {
            
        }

        public static SimpleSingelton CurrentInstance
        {
            get
            {
                if(_instance == null)
                {
                    _instance = new SimpleSingelton();
                }
                return _instance;
            }
        }

        public void Print()
        {
            Console.WriteLine(this.GetHashCode());
        }
    }
}

In our SimpleSingelton class we have created a private constructor. This will ensure that no one else can instantiate SimpleSingelton by calling its constructor.

We have also create a private data member of type SimpleSingelton. This will hold the lone instance of SimpleSingelton. We have marked it static because we will access it from static members (property or method).

We have created a static property which will check if _instance is null or not. If it is null it will instantiate it and then return the _instance.

This implementation looks promising but it is not thread safe. In a multi-threaded scenario two threads can check for the nullability of _instance almost at the same time and thus can create two instances of SimpleSingelton as both will find _instance null.

Partially Thread Safe Implementation


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace PlayingWithSingelton
{
    public class PartiallyThreadSafeSingelton
    {
        private static volatile PartiallyThreadSafeSingelton _instance;
        private static readonly Object Locker = new object();

        private PartiallyThreadSafeSingelton()
        {
            
        }

        public static PartiallyThreadSafeSingelton CurrentInstance
        {
            get
            {
                if(_instance == null)
                {
                    lock (Locker)
                    {
                        _instance = new PartiallyThreadSafeSingelton();
                    }
                }

                return _instance;

            }
        }
    }
}

In our PartiallyThreadSafeSingelton class we have marked the _instance as volatile this means that the most up-to date  value of _instance will be used and the value will be requested every time we will use _instance although in the previous statements _instance value would have been retrieved.

In our getter for CurrentInstance we have use a lock. This will ensure that only one thread will create an instance at a time. Wait!!! But, multiple threads can check for nullability simulatneously and then one thread can wait for the other to create instance and release lock. Then it will also create an instance.

What if we check for nullability just before instantiating? Yes, we should.

Process intensive Thread Safe Implementation


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlayingWithSingelton
{
    public class ProcessIntensiveThreadSafeSingelton
    {
        private static volatile ProcessIntensiveThreadSafeSingelton _instance;
        private static readonly Object Locker = new object();

        private ProcessIntensiveThreadSafeSingelton()
        {
            
        }

        public static ProcessIntensiveThreadSafeSingelton CurrentInstance
        {
            get
            {
                lock (Locker)
                {
                    if (_instance == null)
                        _instance = new ProcessIntensiveThreadSafeSingelton();
                }
                return _instance;
                
            }
        }
    }
}

It is process intensive to acquire a lock every time. As the instantiation will happen only once. Thus we can change our implementation a bit and can check for nullability one more time but before acquiring lock.

Thread Safe Implementation


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlayingWithSingelton
{
    public class ThreadSafeSingelton
    {
        private static volatile ThreadSafeSingelton _instance;
        private static readonly Object Locker = new object();

        private ThreadSafeSingelton()
        {
            
        }

        public static ThreadSafeSingelton CurrentInstance
        {
            get
            {
                if (_instance == null)
                {
                    lock (Locker)
                    {
                        if (_instance == null)
                            _instance = new ThreadSafeSingelton();
                    }
                }
                return _instance;
                
            }
        }
    }
}

In future posts we will discuss more about singelton and its usage.

Comments

Popular posts from this blog

Create a background / taskbar application in c# .NET

Recently, I was working on integration of two windows applications. First application will launch the second application on login and then they both will communicate using pre-defined set of instructions. There were some complications (I am not going into them) and thus we decided to have a third application which actually will act as mediator. First application will launch the mediator (third application) and it will launch the second application. For this purpose we needed to create a task bar application (which will run in background). How To ·          Create a new windows project and delete the default form (Form1). ·          In Program.cs create a new class and inherit it from Form. ·          Please refer the code below. ·          Now change the Main method. In Application.Run change the startup objec...

Check SQL Server Job status (State) using sp_help_job and xp_sqlagent_enum_jobs

This article is about checking the status of a SQL job. In our work place we have lot of SQL jobs. These jobs will run whole day and are business critical. They will load the data and generate extracts which will be used by business people. Thus, it becomes quite essential to support the system efficiently so that the job finishes in time and as desired. Also, while designing a new system sometimes we need to check the dependency of one job over another. In such scenario we need to check whether a particular job has finished or not. All this can be achieved in SQL Server by using the procedures:- sp_help_job xp_sqlagent_enum_jobs Note: xp_sqlagent_enum_jobs is an undocumented proc inside of sp_help_job and is used extensively to get SQL agent job information. sp_help_job: This procedure gives some insight into the status, and information, about a job. This stored procedure provides information such as last start time, job status etc. Syntax sp_help_job { [ @job_id= ] jo...

Java 8 JMX Default Metrics

This is more of a note. Here you can find default types and attributes for JMX on top of Java 8. Code: I will clean and explain it later :( private static void WriteAttributes(final MBeanServer mBeanServer, final ObjectName http) throws InstanceNotFoundException, IntrospectionException, ReflectionException { MBeanInfo info = mBeanServer.getMBeanInfo(http); MBeanAttributeInfo[] attrInfo = info.getAttributes(); System.out.println("Attributes for object: " + http +":\n"); for (MBeanAttributeInfo attr : attrInfo) { System.out.println(" " + attr.getName() + "\n"); } } Attributes for object: java.lang:type=MemoryPool,name=Metaspace:   Name   Type   Valid   Usage   PeakUsage   MemoryManagerNames   UsageThreshold   UsageThresholdExceeded   UsageThresholdCount   UsageThresholdSupported   CollectionUsageThreshold   Collectio...