2014-04-05 219 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'參數。 –