保持静态易失性ISessionFactory

时间:2016-05-19 15:08:34

标签: c# design-patterns nhibernate fluent-nhibernate sessionfactory

我有一个会话工厂的实现,就像这样单身:

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

如果我删除静态变量_instance的volatile,我会通过这个更改获得一些好处吗?或者这是一个很好的练习模式?

1 个答案:

答案 0 :(得分:1)

如果您只是从_instance字段中删除volatile,则代码将不再是线程安全的。

如果你真的想保持着名的#34;双重检查锁定技术您可以从_instance字段中删除volatile,但是您需要将分配修改为如下所示:

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

这将为您带来一些好处,因为_instance字段不再是volatile,因此所有读取都不是易失性的(一些性能提升)。但是我们有一个volatile赋值,它可以保证代码仍然是线程安全的。

我的个人意见 - 不要使用双重检查锁定技术。如果你真的需要延迟初始化使用Lazy类。如果您不需要100%延迟初始化,请按以下方式编写:

private static readonly MySessionFactory _instance = new MySessionFactory();

此初始化将由静态类构造函数调用,该代码在第一次代码尝试访问类的成员时自动调用。在CLR构造函数中,设计是线程安全的,因此在这种情况下您不必担心并发性。而且,在您的情况下,您没有该类的任何与MySessionFactory _instance无关的成员,此解决方案将像双重检查锁一样懒惰。

如果你想了解更多关于这一点的信息,请参阅Jeffrey Richters的书CLR via C#中的一整章,称为#34; The Famous Double-Check Locking Technique&#34;。好读;)