I am working on a multithreaded c# application which is consuming a WCF web service. The connection to the webservice will have a specific timeout which we can define and after which it will close. I am looking to store the connection to the web service using singleton class. I am trying to get the instance as follows :
CLazySingleton ins = CLazySingleton.Instance;
string connection = CLazySingleton.abc;
Below is the code for the singleton class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LazySingleton
{
public class CLazySingleton
{
private static readonly Lazy<CLazySingleton> _instance
= new Lazy<CLazySingleton>(() => new CLazySingleton());
private static readonly object ThreadLock = new object();
public static string abc;
//I will use the service connection object in place of 'abc' in the application
//assume that 'abc' is storing the connection object
private CLazySingleton()
{ }
public static CLazySingleton Instance
{
get
{
if (abc == null)
{
lock (ThreadLock)
{
//Make the connection
abc = "Connection stored in this variable";
Console.WriteLine("Connection Made successfully");
return _instance.Value;
}
}
else
{
return _instance.Value;
}
}
}
}
}
My questions are : 1. Would this code be able to take care of multiple threads trying to get the instance at the same time ? This is currently my biggest concern. 2. Can I have a better solution for this ? 3. Do I need to use 'lock' here or using Lazy approach takes care of multithreads trying to get the instance ?
Any help would be appreciated.
Thanks !
According to Microsoft's Lazy Initialization documentation, under the section titled "Thread-Safe Initialization":
By default, Lazy objects are thread-safe.
With this in mind, your abc
field needn't be static. As you're using a Lazy<T>
to instantiate your singleton, it's safe to initialise your connection in the CLazySingleton
constructor.
Would this code be able to take care of multiple threads trying to get the instance at the same time ?
In your scenario can be the "abc" field initialized twice. Imagine situation, that "abc" variable is null. First thread will be inside the "lock" block before the value assignment. Second thread will be waiting before the lock. So the first thread will initialize the "abc" and second thread will reinitialize it (your check for null is outside of lock, that's the reason). But maybe this is not something you should be afraid of.
Can I have a better solution for this ?
Yes you can. Let me describe it in the last block of this answer.
Do I need to use 'lock' here or using Lazy approach takes care of multithreads trying to get the instance ?
Creation of the Value property in Lazy class is thread safe. In your scenario I would use the advantage of property IsValueCreated of Lazy<> class. You will still need the ThreadLock object as well. Just one more thing is, that once you access Value property of Lazy<> class, IsValueCreated property will return true (that's the trick ;-) )
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LazySingleton
{
public class CLazySingleton
{
private static readonly Lazy<CLazySingleton> _instance
= new Lazy<CLazySingleton>(() => new CLazySingleton());
private static readonly object ThreadLock = new object();
public static string abc;
//I will use the service connection object in place of 'abc' in the application
//assume that 'abc' is storing the connection object
private CLazySingleton()
{ }
public static CLazySingleton Instance
{
get
{
if (_instance.IsValueCreated)
{
return _instance.Value;
}
lock (ThreadLock)
{
if (abc == null)
{
abc = "Connection stored in this variable";
Console.WriteLine("Connection Made successfully");
}
}
return _instance.Value;
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With