2010-03-26 49 views
3

目前,我有以下類:Structuremap單例線程安全嗎?

public class PluginManager 
{ 
    private static bool s_initialized; 
    private static object s_lock = new object(); 

    public static void Initialize() { 
     if (!s_initialized) { 
      lock (s_lock) { 
       if (!s_initialized) { 
        // initialize 

        s_initialized = true; 
       } 
      } 
     } 
    } 
} 

這裏最重要的是,初始化()應該只執行一次,同時應用程序運行。我以爲我會重構爲一個單獨的類這一點,因爲這將是更多的線程安全?:

public sealed class PluginService 
{ 
    static PluginService() { } 
    private static PluginService _instance = new PluginService(); 
    public static PluginService Instance { get { return _instance; } } 

    private bool s_initialized; 

    public void Initialize() { 
     if (!s_initialized) 
     { 
      // initialize 

      s_initialized = true; 
     } 
    } 
} 

問題之一,它仍然需要在這裏有鎖(我已刪除了它),因爲我們將只正在研究同一個實例?

最後,我想用DI和結構圖來初始化我servcices所以我重構如下:

public interface IPluginService { 
    void Initialize(); 
} 

public class NewPluginService : IPluginService 
{ 
    private bool s_initialized; 
    public void Initialize() { 
     if (!s_initialized) { 
      // initialize 

      s_initialized = true; 
     } 
    } 
} 

而且在我的註冊表:

  ForRequestedType<IPluginService>() 
      .TheDefaultIsConcreteType<NewPluginService>().AsSingletons(); 

可正常工作(單在下面的代碼中返回true):

  var instance1 = ObjectFactory.GetInstance<IPluginService>();   
     var instance2 = ObjectFactory.GetInstance<IPluginService>(); 

     bool singleton = (instance1 == instance2); 

所以我的下一個問題,是結構映射解決方案作爲單例類的線程安全(第二個示例)。唯一的缺點是,這仍然允許NewPluginService直接實例化(如果不使用結構映射)。

非常感謝, 本

回答

3

我會做幾個建議:

  • 布爾標誌應該是volatile
  • 讓你的單一實例readonly
  • 初始化不是線程安全的,不管事實上你只有一個實例...所以它應該同步

    public sealded class PluginService 
    { 
    
    static PluginService() { } 
    
    //make the instance readonly 
    private static readonly PluginService _instance = new PluginService(); 
    public static PluginService Instance { get { return _instance; } } 
    
    // make the flag volatile 
    private static volatile bool s_initialized = false; 
    private static object s_lock = new object(); 
    
    
    // you still need to synchronize when you're initializing 
    public void Initialize() { 
        lock(s_lock) 
        { 
         if (!s_initialized) 
         { 
          // initialize 
    
           s_initialized = true; 
          } 
         } 
        } 
    } 
    

有結構化的地圖上沒有競爭,所以它的線程安全似乎沒有受到影響......

你有沒有線程安全的單例類。要記住的主要事情是單個實例不能確保單個線程只能訪問它。如果有多個線程對實例有引用,那麼實例和它所持有的數據之間會存在爭用。如果存在爭用,那麼你應該確保線程安全(至少同步)。

+0

@Lirik - 偉大的幫助謝謝。當使用結構圖獲取實例時,這些建議中的哪一個會適用? – 2010-03-28 14:16:01

+0

@Ben你是否每次從結構化地圖中獲取實例時都要初始化實例?您是否從多個線程訪問結構化映射以獲取實例? – Kiril 2010-03-28 15:26:48

+0

@Lirik - 這真是我的觀點--StructureMap有一個方法AsSingletons用於將實例標記爲單例。我想知道的是,這是否會提供與硬編碼單例相同的線程安全性(除了您的建議)。 – 2010-03-28 16:18:29