线程安全的单例

时间:2014-04-05 12:35:58

标签: c# multithreading lazy-evaluation

我有一个有3个静态成员的类。每个静态成员都不是线程安全的单例。 我需要提供一个线程安全的实现供它们使用。没关系吗?或者我需要为每个实现提供线程安全的包装?如果我应该 - 我怎样才能使用Lazy<T>

其他问题:Measure() Do()SingeltonClass1/2/3的{​​{1}}不是线程安全的func1()线程安全吗?

 public class MyLazySingleton
 {
     // static holder for instance, need to use lambda to construct since constructor private
    private static readonly Lazy<MyLazySingleton> _instance
        = new Lazy<MyLazySingleton>(() => new MyLazySingleton());

     // private to prevent direct instantiation.
     private MyLazySingleton()
     {
             s_c1 = SingletonClass1.Instance();
             s_c2 = SingletonClass2.Instance();
             s_c3 = SingletonClass3.Instance();
    }

    // accessor for instance
    public static MyLazySingletonInstance
    {
        get
        {
            return _instance.Value;
        }
    }
    public void func1()
    {
        if (s_s1.Measure() || s_c2.Measure())
        {
           c_c3.Do();
        }
    }
       static SingletonClass1 s_c1 = null;
       static SingletonClass1 s_c2 = null;
       static SingletonClass1 s_c3 = null;
}

如果构造函数应该获得2个参数,我应该如何重新实现MyLazySingleton? string strint i

我已经提出了跟进问题Thread-safe methods in the singleton class

2 个答案:

答案 0 :(得分:1)

它是线程安全的。

Lazy<T> LazyThreadSafetyMode的默认值为ExecutionAndPublication

来自new Lazy<T>(Func<T>) constructor上的MSDN页面:

  

可以使用使用此构造函数创建的实例   同时来自多个线程。

     

使用初始化的Lazy实例的线程安全模式   这个构造函数是LazyThreadSafetyMode.ExecutionAndPublication。

如果您使用another overload可以传递不同的 LazyThreadSafetyMode值,那么它就不是线程安全的。但是现在使用构造函数,它是线程安全的。

编辑:关于您的其他已编辑问题,如果SingletonClass1类型上的那些方法线程安全:那么func1是也不是线程安全的。

来自Lazy<T> MSDN Page

  

使Lazy对象线程安全无法保护懒惰   初始化对象。如果多个线程可以访问懒惰   初始化对象,您必须使其属性和方法安全   多线程访问。

您需要确保这些类之间的那些方法/交互是线程安全的。这个可能就像使用func1语句包装lock正文一样简单,但我不能肯定地说明取决于SingletonClass1的3个实例的方式互相交流或调用代码如何访问它们。

答案 1 :(得分:0)

要确保线程安全,您必须设置LazyThreadSafetyMode构造函数的Lazy<T>参数。有3个可用值:

  • None:不是线程安全的
  • PublicationOnly:可能会创建许多MyLazySingleton个实例,但Value属性只会发布/返回一个实例。在内部,它使用Interlocked.CompareExchange
  • ExecutionAndPublication:值只创建一次

以下是一个例子:

new Lazy<Test>(() => new Test(), LazyThreadSafetyMode.ExecutionAndPublication)