it may be basic question
to have a singleton in multi-threaded environment we can use a lock. Please refer the code snippet. But why do we need double-checked locki
If you create the object in the field initialiser, you don't need the lock:
class singleton
{
private static singleton instance = new singleton();
private static singleton() { }
public static singleton Instance
{
get { return instance; }
}
}
Also - bear in mind that the lock is only controlling the creation of the object, the object would still need to be thread-safe if you're using it in multiple threads.
Multithreaded Singleton : The best approach to use double check locking
public sealed class Singleton
{
private static volatile Singleton _instance;
private static readonly object InstanceLoker= new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (InstanceLoker)
{
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
}
And with .Net 4.x and newer you should defer to the Lazy class when possible as this pattern is used with the Initialization And Publication option. (note: the inverse is available as well where creation isn't thread safe but the publication of the instance is via the Publication option)
Jon Skeet explains this in detail.
Locks are expensive.
If the object already exists, there's no point in taking out a lock.
Thus, you have a first check outside the lock.
However, even if the object didn't exist before you took the look, another thread may have created it between the if
condition and the lock
statement.
Therefore, you need to check again inside the lock.
However, the best way to write a singleton is to use a static
constructor:
public sealed class Singleton
{
private Singleton()
{
}
public static Singleton Instance { get { return Nested.instance; } }
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
When we try to execute the method of the singleton class using Parallel libraries. It doesn’t recognize the singleton behavior because of multi threading is executing in TPL which causes to failure of concept Singleton Pattern . To overcome this problem there is concept of the locking of the object so that at a time only one thread can access it. But this is not efficient approach because involvement of lock checking creates unnecessary watches to the object. To avoid it we make use “Double locking checking”
The "best" way I know is this:
public class MySingleton {
// object for synchronization
private static readonly object syncRoot = new object();
// the singleton instance
private static MySingleton @default;
public static MySingleton Default {
get {
// geting singleton instance without locking
var result = @default;
// if result is NOT null, no additional action is required
if ( object.ReferenceEquals(result, null) ){
// lock the synchronization object
lock(syncRoot) {
// geting singleton instanc in lock - because
// the value of @default field could be changed
result = @default;
// checking for NULL
if ( object.ReferenceEquals(result, null) ) {
// if result is NULL, create new singleton instance
result = new MySingleton();
// set the default instance
@default = result;
}
}
}
// return singleton instance
return result;
}
}
}