Are C# static class private fields thread safe?

  • A+
Category:Languages

I have a C# static class accessed from multiple threads. Two questions:

  1. Are my private static fields thread safe when the field is initialized on declaration?
  2. Should I lock when creating private static fields from within static constructor?

Usage of static class from different threads:

class Program     {         static void Main(string[] args)         {             for (int i = 0; i < 100; i++)             {                 Task.Run(() =>                 {                     string name = MyStaticClass.GetValue(9555);                     //...                 });             }         } } 

Option 1 of static class:

public static class MyStaticClass     {         private static MyClass _myClass = new MyClass();          public static string GetValue(int key)         {             return _myClass.GetValue(key);         }     } 

Option 2 of static class:

public static class MyStaticClass     {         private static MyClass _myClass;         private static object _lockObj = new object();          static MyStaticClass()         {             InitMyClass();         }          private static void InitMyClass()         {             if (_myClass == null)             {                 lock(_lockObj)                 {                     if (_myClass == null)                     {                         _myClass = new MyClass();                     }                 }             }         }          public static string GetValue(int key)         {             return _myClass.GetValue(key);         }     } 

Instance class created from the static class:

public class MyClass     {         private Dictionary<int, Guid> _valuesDict = new Dictionary<int, Guid>();          public MyClass()         {             for (int i = 0; i < 10000; i++)             {                 _valuesDict.Add(i, Guid.NewGuid());             }         }          public string GetValue(int key)         {             if (_valuesDict.TryGetValue(key, out Guid value))             {                 return value.ToString();             }              return string.Empty;         }     } 

 


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.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: