简体   繁体   English

ThreadStatic的C#Singleton模式设计

[英]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.) 它不起作用(抛出NullReferenceException并且没有创建实例。)

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 ? 请问有人解释一下吗?

Instead of using [ThreadStatic] then you could use ThreadLocal<T> which will essentially achieve what you're trying with [ThreadStatic] . 您可以使用ThreadLocal<T>代替使用[ThreadStatic] ,这将基本上实现您使用[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. 有关详细信息,请参阅: https//msdn.microsoft.com/en-us/library/dd642243(v = vs.110).aspx

Edit: To answer your question. 编辑:回答你的问题。

In C# when doing: 在C#中做的时候:

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 . 无论它是否用[ThreadStatic]标记,它只会创建一个静态构造函数来设置SingletonClass的实例。

C# does not have the ability to create static constructors per threads. C#没有能力为每个线程创建静态构造函数。

That's what you can use ThreadLocal<T> for. 这就是你可以使用ThreadLocal<T>的原因。 If we take your code as an example then the default constructor for SingletonClass essentially becomes the "thread-static" constructor. 如果我们以您的代码为例,那么SingletonClass的默认构造函数实际上就变成了"thread-static"构造函数。

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. 在第二个示例中, _instance字段在声明时初始化。 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): 这意味着你最终会得到这样的东西(没有复制IL代码,因为它更难理解):

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. 无论您拥有多少线程,CLR都会确保只调用一次静态构造函数。 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). 查看上面的代码,这意味着对于您创建的两个Tasks, _instance字段将只初始化一次(因为只有一次调用静态构造函数)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM