Is the C# Static Constructor Thread Safe

Is the C# static constructor thread safe?

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();
}
}

Is static constructor really thread safe?

Thread safe is not a particularly helpful phrase to use. You should generally avoid using it as it doesn't really tell you what operations are and are not safe.

Instead it's important to specifically state what thread-related operations and situations are supported in any given context. One can then objectively and clearly state whether the expectations are violated.

C# will ensure that static constructors are run at some point before they are used, no matter how many threads might use the class, or whether another thread is currently running the static constructor.

C# will ensure that it doesn't run the static constructor more than once, no matter how many different threads might be using the same class at around the same time, or whether another thread uses a class while it is currently being initialized.

The specs specifically state that if a static constructor throws an exception in the one time that it runs then all future uses of that type will throw a TypeInitializationException, which is what you are seeing.

The behavior that you are seeing is entirely in line with the behavior defined in the specifications.

Using static get only property thread safe?

Is there a chance that while a thread is referencing MyFoo.Foo another thread that reference it will get an uncompleted or un-initialized data back b/c the InitFoo() is not complete yet?

No. Type initialization is thread-safe:

  • No other threads get to use your type while it's being initialized by another thread
  • All writes to memory performed by the initialization thread are made visible to other threads when the initialization has been performed

There's one wrinkle which is that if the same thread that's initializing MyFoo ends up reading MyFoo._foo before it's finished initializing, that will cause a problem. That can be particularly awkward to diagnose if there are types that depend on each other for initialization in a cycle.

Here's an example, with two type initializers that each use a value from the other. They both have static constructors to make the behavior deterministic. (The rules for when types are initialized depend on whether or not they have static constructors.)

using System;

public class Program
{
public static void Main(string[] args)
{
// Determine which type to initialize first based on whether there
// are any command line arguemnts.
if (args.Length > 0)
{
Class2.DoNothing();
}
Console.WriteLine($"Class1.Value1: {Class1.Value1}");
Console.WriteLine($"Class2.Value2: {Class2.Value2}");
}
}

public class Class1
{
public static readonly string Value1 =
$"When initializing Class1.Value1, Class2.Value2={Class2.Value2}";

static Class1() {}
}

public class Class2
{
public static readonly string Value2 =
$"When initializing Class2.Value2, Class2.Value2={Class1.Value1}";

static Class2() {}

public static void DoNothing() {}
}

Running this without any command line arguments, Class1 starts initializing first, which in turn initializes Class2:

Class1.Value1: When initializing Class1.Value1, Class2.Value2=When initializing Class2.Value2, Class2.Value2=
Class2.Value2: When initializing Class2.Value2, Class2.Value2=

With any command line argument, we initialize Class2 first, which in turn initializes Class1:

Class1.Value1: When initializing Class1.Value1, Class2.Value2=
Class2.Value2: When initializing Class2.Value2, Class2.Value2=When initializing Class1.Value1, Class2.Value2=

Is a C# Constructor thread safe?

This depends very much on the implementation of the constructor.

If the constructor is only accessing members of that class, and not any external static classes or methods, then yes - it is thread safe.

But if that constructor is accessing non-threadsafe objects that exist outside of the class itself, (such as a global singleton), then it is not threadsafe.

update: The constructor should be careful not to access any static members of the class that are not readonly or const. (thanks Nathan A and LVBen)

Are C# static class private fields thread safe?

Should I lock when initializing private static fields from within static constructor?

Let's not bury the lede here:

Never lock in a static constructor. Static constructors are already locked by the framework so that they run on one thread exactly once.

This is a special case of a more general bit of good advice: never do anything fancy with threads in a static constructor. The fact that static constructors are effectively locked, and that lock can be contested by any code that accesses your type, means that you can very quickly get into deadlocks that you did not expect and are hard to see. I give an example here: https://ericlippert.com/2013/01/31/the-no-lock-deadlock/

If you want lazy initialization, use the Lazy<T> construct; it was written by experts who know how to make it safe.

Are my private static fields thread safe when the field is initialized on declaration?

Thread safety is the preservation of program invariants when program elements are called from multiple threads. You haven't said what your invariants are, so it is impossible to say if your program is "safe".

If the invariant you are worried about is that the static constructor is observed to run before the first static method is executed, or the first instance is created, of a type, C# guarantees that. Of course, if you write crazy code in your static constructor, then crazy things can happen, so again, try to keep your static constructors very simple.

Instance constructor sets a static member, is it thread safe?

@ajmastrean

I am not saying you should use the singleton pattern itself, but adopt its method of encapsulating the instantiation process.

i.e.

  • Make the constructor private.
  • Create a static instance method that returns the type.
  • In the static instance method, use the lock keyword before instantiating.
  • Instantiate a new instance of the type.
  • Increment the count.
  • Unlock and return the new instance.

EDIT

One problem that has occurred to me, if how would you know when the count has gone down? ;)

EDIT AGAIN

Thinking about it, you could add code to the destructor that calls another static method to decrement the counter :D

Thread-safety of static initializers in C#

Case 2 will be honoured. A class field, property, or method cannot be dereferenced until the type has been initialized, and the type will not be initialized until the static constructor is completed. The static constructor is, to the best of my knowledge, therefore a blocking call.

http://msdn.microsoft.com/en-us/library/aa645612(v=vs.71).aspx

"The static constructor for a class executes at most once in a given application domain."

See this reply from Eric Lippert: https://stackoverflow.com/a/9399027/2420979 and note that "cctor" is IL for static constructor.

No cctors call MyMethod, directly or indirectly! Now is it ever possible for a static method like MyMethod to be called before the cctor of MyClass completes?

No.

Is that still true even if there are multiple threads involved?

Yes. The cctor will finish on one thread before the static method can be called on any thread.

Can the cctor be called more than once? Suppose two threads both cause the cctor to be run.

The cctor is guaranteed to be called at most once, no matter how many threads are involved. If two threads call MyMethod "at the same time" then they race. One of them loses the race and blocks until the MyClass cctor completes on the winning thread.

C# static constructor initialization thread safety while filling ConcurrentDictionary

This is a static constructor deadlock. The parallel threads access PersonDB which blocks until PersonDB is statically initialized. Move the initialization code to a different function. Make it return the dictionary instead of modifying pDict in place.

I try to avoid static constructors that do things that can fail. Your code certainly can fail because it is IO. If it does the class is permanently hosed. Lazy can be better.



Related Topics



Leave a reply



Submit