Introduction
Why do we even need a singleton pattern? Consider a situation where you only want to create one instance of the class. For example, let’s say you’re calling an API in your project, as every API’s first step is to authenticate the client. After successful authentication, the server generates a session, which is alive for some time. Imagine for every single request you're creating a session, which is wrong at so many levels. You should only create a session once at use that session for all other requests (for example, Facebook's login to logout is one session). This is where we should use the singleton pattern.
  1. namespace SingletonPattern
  2. {
  3. /// <summary>
  4. /// Basic implementation of Singleton design pattern
  5. /// </summary>
  6. class SingletonExample
  7. {
  8. /// <summary>
  9. /// As there is single instance for entire project it has to be static.
  10. /// </summary>
  11. private static SingletonExample obj;
  12. /// <summary>
  13. /// Default constructor
  14. /// </summary>
  15. public SingletonExample()
  16. {
  17. }
  18. /// <summary>
  19. /// static method which initialise our static instance
  20. /// </summary>
  21. /// <returns>SingletonExample</returns>
  22. public static SingletonExample Initialise()
  23. {
  24. if(obj == null)
  25. {
  26. obj = new SingletonExample();
  27. }
  28. return obj;
  29. }
  30. }
  31. }
As you see in the above code we have static Initialise() method, so whenever your project calls this method for the first time, it creates a new object then after that it will just return the same instance.
There's a problem with the above code, as it's not thread-safe. It creates an instance for every thread that makes a request.
It's ok, no need to panic, as we have a solution for such cases. We have 2 keywords to help us out:
Volatile and Synchronised
Volatile (in brief):
In a multiThreaded scenario, one Thread which has a processor can cache some resource (properties/variables) out of your class in its cache memory for faster processing and where the other Thread holding the same old values resource which is on RAM. Here we have a mismatch issue, so in order to avoid that we use volatile. It makes sure cache data is updated on RAM and vice-versa.
Synchronised (in brief):
Synchronization allows only one thread to access the resource at a time. No other thread can get access to that resource until the assigned thread finishes its task. Threads execute asynchronously. Synchronization helps us by making threads synchronized.
We can use a locking mechanism to make it thread-safe.
C# Implementation (unsynchronized in C#, but we have a workaround)
  1. /// <summary>
  2. /// Basic implementation of Singleton design pattern
  3. /// </summary>
  4. class SingletonExample
  5. {
  6. /// <summary>
  7. /// As there is single instance for entire project it has to be static.
  8. /// </summary>
  9. private volatile static SingletonExample obj = null;
  10. /// <summary>
  11. /// static object class instance
  12. /// </summary>
  13. private static readonly object SyncLock = new object();
  14. /// <summary>
  15. /// Default constructor
  16. /// </summary>
  17. public SingletonExample()
  18. {
  19. }
  20. /// <summary>
  21. /// static method which initialise SingletonExample
  22. /// </summary>
  23. /// <returns>instance of SingletonExample</returns>
  24. public static SingletonExample Initialise()
  25. {
  26. if(obj == null)
  27. {
  28. lock (SyncLock)
  29. {
  30. if (obj == null)
  31. {
  32. obj = new SingletonExample();
  33. }
  34. }
  35. }
  36. return obj;
  37. }
  38. }
In Java we have synchronized keyword to take the pain away.
  1. class SingletonExample
  2. {
  3. /// <summary>
  4. /// As there is single instance for entire project it has to be static.
  5. /// </summary>
  6. private volatile static SingletonExample obj;
  7. /// <summary>
  8. /// Default constructor
  9. /// </summary>
  10. public SingletonExample()
  11. {}
  12. /// <summary>
  13. /// static method which initialise our static instance
  14. /// </summary>
  15. /// <returns>SingletonExample</returns>
  16. public static SingletonExample Initialise()
  17. {
  18. if(obj == null)
  19. {
  20. synchronized(SingletonExample.class)
  21. {
  22. if (obj == null)
  23. obj = new SingletonExample();
  24. }
  25. }
  26. return obj;
  27. }
  28. }
Thank you so much for visiting this blog, I hope you were helped by this. If you have any queries, please connect with me.
Have a good day :)