Singleton
in C#
The singleton pattern is a
design pattern used to implement the mathematical concept of a
singleton, by restricting the instantiation of a
class to one object.
If we need a class that has only one then we need
Singleton implementation. We also want to make sure that your solution is
thread-safe and give simple access to the instance.Singleton is used where we
need a class that has only one instance and usually gives simple access o the
instance.
Singleton
Singleton Design Patterns (Lazy initialization)
using System;
public class Singleton
{
private static Singleton instance;
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
The main
disadvantage of this implementation, however, is that it is not thread- safe.
If separate threads of execution enter the Instance property method at the same time, more
that one instance of the Singleton object may be created. Each thread
could execute the following statement and decide that a new instance has to be
created:
if (instance == null)
Static
Initialization
Thread-safe without using
locks
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
}
The class is marked sealed to prevent derivation,
which could add instances. The variable is marked readonly, which means that it can be assigned only during static
initialization or in a class
constructor.
Multithreaded
Singleton
The following implementation allows only a
single thread to enter the critical area, which the lock block identifies, when
no instance of Singleton has yet been created:
using System;
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
The thread takes out a lock on a shared object, and then checks
whether or not the instance has been created before creating the instance. This
is thread-safe implementation.
This approach ensures that only one instance
is created and only when the instance is needed. Also, the variable is declared
to be volatile to ensure that
assignment to the instance variable completes before the instance variable can
be accessed. Lastly, this approach uses a syncRoot instance to lock on,
rather than locking on the type itself, to avoid deadlocks.