5

我想弄清楚单例模式设计。我想为我的单例类中的每个线程创建单独的实例。所以我在下面提供了两个设计。

这是工作

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()
    {

    }
}

它不起作用(抛出 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()
    {

    }
}

我真的很想知道为什么不为第二个设计创建一个实例。有人可以解释一下吗?

4

2 回答 2

4

而不是使用[ThreadStatic]then 你可以使用ThreadLocal<T>which 将基本上实现你正在尝试的[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()
    {

    }
}

有关详细信息,请参阅:https ://msdn.microsoft.com/en-us/library/dd642243(v=vs.110).aspx。

编辑:回答你的问题。

在 C# 中做时:

private static SingletonClass _instance = new SingletonClass();

不管它是否被标记,[ThreadStatic]它只会创建一个静态构造函数来设置SingletonClass.

C# 无法为每个线程创建静态构造函数。

这就是你可以使用ThreadLocal<T>的。如果我们以您的代码为例,那么默认构造函数SingletonClass本质上就是"thread-static"构造函数。

于 2017-11-11T14:26:28.437 回答
3

您的问题的答案主要与类字段的初始化方式有关。

在第二个示例中,该_instance字段在声明时被初始化。每次在声明时初始化静态字段时,都会创建一个静态构造函数(如果您尚未声明它)。在编译时,初始化将被移动到静态构造函数中。这意味着你最终会得到这样的东西(没有复制 IL 代码,因为它更难理解):

public sealed class SingletonClass
{
    [ThreadStatic]
    private static SingletonClass _instance;

    public static SingletonClass Instance
    {
        get
        {
            return _instance;
        }
    }
    static SingletonClass()
    {
        _instance = new SingletonClass();
    }
}

CLR 确保静态构造函数只被调用一次,不管你有多少线程。看上面的代码,这意味着对于你创建的两个Task,该_instance字段只会被初始化一次(因为只会调用一次静态构造函数)。

于 2017-11-11T17:57:01.220 回答