Is the C# static constructor thread safe?
In other words, is this Singleton implementation thread safe:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance
{
get { return instance; }
}
}
Static constructors are guaranteed to be run only once per application domain, before any instances of a class are created or any static members are accessed. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
The implementation shown is thread safe for the initial construction, that is, no locking or null testing is required for constructing the Singleton object. However, this does not mean that any use of the instance will be synchronised. There are a variety of ways that this can be done; I've shown one below.
public class Singleton
{
private static Singleton instance;
// Added a static mutex for synchronising use of instance.
private static System.Threading.Mutex mutex;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
mutex = new System.Threading.Mutex();
}
public static Singleton Acquire()
{
mutex.WaitOne();
return instance;
}
// Each call to Acquire() requires a call to Release()
public static void Release()
{
mutex.ReleaseMutex();
}
}
While all of these answers are giving the same general answer, there is one caveat.
Remember that all potential derivations of a generic class are compiled as individual types. So use caution when implementing static constructors for generic types.
class MyObject<T>
{
static MyObject()
{
//this code will get executed for each T.
}
}
EDIT:
Here is the demonstration:
static void Main(string[] args)
{
var obj = new Foo<object>();
var obj2 = new Foo<string>();
}
public class Foo<T>
{
static Foo()
{
System.Diagnostics.Debug.WriteLine(String.Format("Hit {0}", typeof(T).ToString()));
}
}
In the console:
Hit System.Object
Hit System.String
Using a static constructor actually is threadsafe. The static constructor is guaranteed to be executed only once.
From the C# language specification:
The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
- An instance of the class is created.
- Any of the static members of the class are referenced.
So yes, you can trust that your singleton will be correctly instantiated.
Zooba made an excellent point (and 15 seconds before me, too!) that the static constructor will not guarantee thread-safe shared access to the singleton. That will need to be handled in another manner.
Here's the Cliffnotes version from the above MSDN page on c# singleton:
Use the following pattern, always, you can't go wrong:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
}
Beyond the obvious singleton features, it gives you these two things for free (in respect to singleton in c++):
- lazy construction (or no construction if it was never called)
- synchronization