This is the code I have in place, running for couple of months with no issues.
public sealed class Singleton
{
private static Singleton value;
private static object syncRoot = new Object();
public static Singleton Value
{
get
{
if (Singleton.value == null)
{
lock (syncRoot)
{
if (Singleton.value == null)
{
Singleton.value = new Singleton();
}
}
}
return Singleton.value;
}
}
}
However, I came across this link and it outlined issues with the above.
a) Write Singleton.value = new Singleton(); may get cached on the processor so the other thread may not end up seeing it. To fix this volatile keyword is used.
Q(1): Doesn't the C# lock keyword take care of this ?
b) Another better solution outlined, in the same article, then is to avoid volatile and introduce System.Threading.Thread.MemoryBarrier(); after the write to Singleton.value.
Question:
Q(2) I don't quite understand the need for MemoryBarrier() after the write. What possible re-ordering could potentially cause the other thread to see Singleton.value as null ? The lock prevents other threads from even reading anything.
Q(3) Barriers will just maintain order but what if the value is still read from some cache instead. Isn't volatile still required ?
Q(4) Is barrier really required there since C# lock itself places it ?
Finally, Do I need to update my code with either approach or is it good enough ?
Edits
There is an answer proposed to use Lazy initialization. I got it.
But what were they trying to accomplish using volatie and memorybarrier that lock doesn't guarantee ?