2010-03-26 50 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