0

volatile statique J'ai une usine d'Implémentation session pour être singleton comme ceci:Gardez ISessionFactory

public sealed class MySessionFactory 
{ 
    private static volatile MySessionFactory _instance; 
    private ISessionFactory _sessionFactory; 
    private static volatile object _locker = new object(); 

    private MySessionFactory() 
    { 

    } 

    public MySessionFactory Intance 
    { 
     get 
     { 
      if (_instance != null) 
       return _instance; 

      lock (_locker) 
      { 
       if (_sessionFactory == null) 
       { 
        _instance = new MySessionFactory(); 
       } 
      } 

      return _instance; 
     } 
    } 

    public ISession OpenSession() 
    { 
     if (_sessionFactory != null) 
      return _sessionFactory.OpenSession(); 

     lock (_locker) 
     { 
      if (_sessionFactory == null) 
      { 
       var cfg = FluentNHibernate.Cfg.Fluently.Configure() 
        .Database(FluentNHibernate.Cfg.Db.PostgreSQLConfiguration.Standard.ConnectionString("connectionString").UseReflectionOptimizer()) 
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsAssembly>()); 
       _sessionFactory = cfg.BuildSessionFactory(); 

      } 
     } 

     return _sessionFactory.OpenSession(); 
    } 
} 

Si je supprime la volatilité de _instance variable statique, je vais obtenir des avantages de ce changement? Ou c'est un modèle de bonne pratique?

+0

Si vous utilisez Lazy , vous atteindrez le même but avec un code plus propre, à mon humble avis. –

Répondre

1

Si vous supprimez simplement volatile de votre champ _instance, votre code ne sera plus sûr pour les threads.

Si vous voulez vraiment garder la technique de verrouillage à double contrôle « célèbre » vous pouvez supprimer volatile de votre champ _instance mais vous devez modifier l'affectation à ressembler à ceci:

var tmp = new MySessionFactory(); 
Volatile.Write(ref _instance, tmp); 

Cela donnera vous avez un certain avantage car le champ _instance n'est plus volatile donc toutes les lectures ne sont pas volatiles (gain de performance). Cependant, nous avons une affectation volatile qui garantira que le code est toujours thread-safe.

Mon opinion personnelle - ne pas utiliser la technique de verrouillage à double contrôle. Si vous avez vraiment besoin d'une initialisation paresseuse, utilisez la classe Lazy. Si vous n'avez pas besoin initialisation paresseuse 100% il suffit d'écrire comme ceci:

private static readonly MySessionFactory _instance = new MySessionFactory(); 

Cette initialisation sera appelée par le constructeur de la classe statique qui est appelée automatiquement le premier code temporel tente d'accéder à un membre de la classe. Dans les constructeurs CLR, la conception est sûre pour les threads. Vous n'avez donc pas à vous soucier de la concurrence dans ce cas. Et puisque dans votre cas vous n'avez aucun membre de cette classe qui ne soit pas lié à MySessionFactory _instance, cette solution se comportera comme un verrou paresseux.

Si vous voulez en savoir plus à ce sujet, il y a un chapitre entier dans le livre CLR via C# de Jeffrey Richters intitulé "La technique de verrouillage à double contrôle". Bonne lecture;)