Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Singleton Pattern Designs for ThreadStatic

I want to figure out about singleton pattern designs. I want to create seperated instances for per thread from my singleton class. So I provided two designs below.

It is Working

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 is not working (Throwing NullReferenceException and instance is not being 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 am really wondering why an instance is not created for second design. Can anybody explain that please ?

like image 842
lucky Avatar asked Nov 11 '17 14:11

lucky


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr. Stroustroupe.

Is C programming hard?

C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.


2 Answers

Instead of using [ThreadStatic] then you could use ThreadLocal<T> which will essentially achieve what you're trying 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 information.

Edit: To answer your question.

In C# when doing:

private static SingletonClass _instance = new SingletonClass();

Regardless if it's marked with [ThreadStatic] or not then it will only create a single static constructor which sets the instance of SingletonClass.

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

That's what you can use ThreadLocal<T> for. If we take your code as an example then the default constructor for SingletonClass essentially becomes the "thread-static" constructor.

like image 153
Bauss Avatar answered Oct 11 '22 05:10

Bauss


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

In the second example, the _instance field is initialized at declaration. Every time a static field is initialized at declaration, a static constructor will be created (if you don't have it declared already). At compile time, the initialization will be moved into the static constructor. This means that you will end up having something like this (didn't 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, regardless of how many threads you have. Looking at the above code, it means that for the two Tasks that you created, the _instance field will be initialized only once (since there will be only one call to the static constructor).

like image 32
Lucian Loghin Avatar answered Oct 11 '22 07:10

Lucian Loghin