C # Singleton Pattern Designs for ThreadStatic

I want to understand the designs of singleton models. I want to create separate instances for a stream from my singleton class. Therefore, I presented two projects below.

Works

class Program { static void Main(string[] args) { Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode())); Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode())); Console.ReadLine(); } } public sealed class SingletonClass { [ThreadStatic] private static SingletonClass _instance; public static SingletonClass Instance { get { if (_instance == null) { _instance = new SingletonClass(); } return _instance; } } private SingletonClass() { } } 

It does not work (Throwing NullReferenceException and instance are not created.)

 class Program { static void Main(string[] args) { Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode())); Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode())); Console.ReadLine(); } } public sealed class SingletonClass { [ThreadStatic] private static SingletonClass _instance = new SingletonClass(); public static SingletonClass Instance { get { return _instance; } } private SingletonClass() { } } 

I really wonder why the instance was not created for the second design. Can someone explain this please?

+5
source share
2 answers

The answer to your question is mainly related to how class fields are initialized.

In the second example, the _instance field _instance initialized upon declaration. Each time a static field is initialized during the declaration, a static constructor is created (if you have not already declared it). At compile time, initialization will be transferred to the static constructor. This means that you will have something like this (did not copy the IL code, as it would be harder to understand):

 public sealed class SingletonClass { [ThreadStatic] private static SingletonClass _instance; public static SingletonClass Instance { get { return _instance; } } static SingletonClass() { _instance = new SingletonClass(); } } 

The CLR ensures that the static constructor is called only once, no matter how many threads you have. If you look at the code above, this means that for the two tasks created, the _instance field will be initialized only once (since there will be only one call for the static constructor).

+3
source

Instead of using [ThreadStatic] you can use ThreadLocal<T> , which essentially achieves what you are trying to use with [ThreadStatic] .

 public sealed class SingletonClass { private static ThreadLocal<SingletonClass> _instance; static SingletonClass() { _instance = new ThreadLocal<SingletonClass>(() => new SingletonClass()); } public static SingletonClass Instance { get { return _instance.Value; } } private SingletonClass() { } } 

See https://msdn.microsoft.com/en-us/library/dd642243(v=vs.110).aspx for more details.

Edit: answer your question.

In C #, when executed:

 private static SingletonClass _instance = new SingletonClass(); 

Regardless of whether it is marked [ThreadStatic] or not, it will create only one static constructor that sets up an instance of SingletonClass .

C # does not have the ability to create static constructors for threads.

What you can use ThreadLocal<T> for. If we take your code as an example, the default constructor for SingletonClass will essentially become the "thread-static" constructor.

+4
source

Source: https://habr.com/ru/post/1273284/


All Articles