2014-04-05 176 views
1

我有一个有3个静态成员的类。每个静态成员不是线程安全的单例。 我需要为它们的使用提供一个线程安全的实现。它可以吗?或者我需要为它们中的每一个提供线程安全的包装?如果我应该 - 我如何使用Lazy<T>做到这一点?线程安全singelton

附加问题:Measure()Do() of SingeltonClass1/2/3不是线程安全的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; 
} 

如何重新实现MyLazySingleton如果它的构造函数应该得到2个参数? string strint i

我曾问一个跟进的问题Thread-safe methods in the singleton class

+0

我编辑了我的答案,包括您的额外编辑/问题。如果您还有其他问题,可能有新的针对性问题。 –

+0

我没有注意到您编辑的底部的第三个问题。您打算如何提供这些参数会影响答案。我建议你创建一个新的问题_specifically_关于这一点。 (是参数编译时常量吗?你会更新你的'MyLazySingletonInstance'来传递它们吗?用户会以某种方式指定它们吗?等等) –

回答

1

这是线程安全的,因为它是。

Lazy<T>的默认值LazyThreadSafetyModeExecutionAndPublication

从MSDN页面上的new Lazy<T>(Func<T>) constructor

与此构造函数创建一个实例可以从多个线程使用 兼任。

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

如果你使用another overload在那里你可以通过一个不同LazyThreadSafetyMode值就不会是线程安全的。但是现在使用构造函数,它是线程安全的。

编辑:关于你提到的附加编辑的问题,如果您SingletonClass1类型的方法线程安全的:然后没有func1不是线程安全的两种。

Lazy<T> MSDN Page

使懒惰对象线程安全没有保障懒洋洋地 初始化的对象。如果多个线程可以访问已初始化的对象,则必须使其属性和方法对多线程访问的安全性为 。

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

0

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

  • None:不是线程安全
  • PublicationOnly:许多MyLazySingleton可以被创建,但只有一个将出版/由Value属性返回。内部它使用Interlocked.CompareExchange
  • ExecutionAndPublication:这个值是创建只有一次

下面是一个例子:

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

Yakov不需要更改构造函数,也不需要指定线程安全。 Lazy的默认值使得它们是线程安全的。为了确保线程安全,Yakov不需要设置'LazyThreadSafetyMode'参数。 –