2010-03-26 7 views
3

Actuellement, j'ai la classe suivante:Est-ce que Structuremap singleton est sûr?

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; 
       } 
      } 
     } 
    } 
} 

L'important est ici que initialize() ne doit être exécutée une fois alors que l'application est en cours d'exécution. Je pensais que je Refactor cela en une classe singleton puisque ce serait plus thread-safe ?:

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; 
     } 
    } 
} 

Première question, est-il encore nécessaire d'avoir la serrure ici (je l'ai enlevé) puisque nous ne jamais travailler sur la même instance?

Enfin, je veux utiliser la carte DI et de la structure pour initialiser mes servcices donc je refondus comme ci-dessous:

public interface IPluginService { 
    void Initialize(); 
} 

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

      s_initialized = true; 
     } 
    } 
} 

Et dans mon registre:

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

Cela fonctionne comme prévu (singleton renvoyer vrai dans le code suivant):

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

     bool singleton = (instance1 == instance2); 

Alors ma prochaine question, est la solution de carte de structure en tant que thread sûr que la classe singleton (deuxième exemple). Le seul inconvénient est que cela permettrait toujours à NewPluginService d'être instancié directement (si vous n'utilisez pas la structure map).

Un grand merci, Ben

Répondre

3

je voudrais faire plusieurs recommandations:

  • le drapeau booléen doit être volatile
  • rendre votre instance singleton readonly
  • l'initialisation est pas thread-safe, indépendamment du fait que vous avez seulement une instance ... donc il devrait être synchronisé

    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; 
          } 
         } 
        } 
    } 
    

Il n'y a pas de conflit sur la carte structurée, de sorte que son fil de sécurité ne semble pas compromise ...

La classe singleton vous aviez été pas thread-safe. La principale chose à retenir est qu'une seule instance ne garantit pas qu'un seul thread peut seulement y accéder. Si plusieurs threads ont une référence à l'instance, il existe un conflit sur l'instance et les données qu'elle contient. S'il y a un conflit, vous devez assurer la sécurité du thread (synchroniser au minimum).

+0

@Lirik - une aide précieuse. Laquelle de ces suggestions s'appliquerait lors de l'utilisation de structemap pour obtenir l'instance? –

+0

@Ben Initialisez-vous l'instance à chaque fois que vous l'obtenez à partir de la carte structurée? Accédez-vous à la carte structurée à partir de plusieurs threads afin d'obtenir des instances? – Kiril

+0

@Lirik - c'était vraiment mon point de vue - StructureMap a une méthode AsSingletons pour marquer une instance comme un singleton. Ce que je voulais savoir, c'est si cela offrait la même sécurité de thread que j'avais avec un singleton codé en dur (en plus de vos suggestions). –

Questions connexes