3

在我的 ASP.NET MVC 项目中,我有一个通过 Structuremap 实例化并配置为单例的类。

鉴于 ASP.NET 本质上是多线程的,并且默认情况下单例模式不是线程安全的,它会导致任何问题吗?

我遇到了一个问题,即为配置为 Singleton 的类返回多个实例。这个问题可能是因为从不同线程请求的实例。

编辑:对这个问题给出了更详细的描述。Singleton中的结构图返回多个实例

EDIT2:这是我的班级所做的描述

class DerviedClass: BaseInterface
{
   ISession session

   DerivedClass()
   {
      session = ObjectFactory.GetInstance<ISession>();
   }

   public bool DoWork
   {
       return session.QueryOver<MyTable>().RowCount() > 0;
   }
}
4

2 回答 2

3

考虑到您的扩展版本,DerviedClass我会说:这是一个非常冒险的示例,并且可能会导致很多问题。

我的担忧:

1)平均售价。NET+ NHibernate==ISession每个请求。换句话说,当应用程序启动时(最有可能由第一个请求触发,如果有自动重启可能会更频繁),创建单例并提供ISession每个当前请求的实例,即第一个请求

至少,ISession应该Factory在需要时通过它接收,可以肯定的是,它与当前请求相关。

2)如果在构造函数中创建的 NHibernateISession旨在独立于Current Request,则可能意味着:

  • 它长时间运行,在更多请求中打开而不是关闭 - 可能存在锁定问题。或者
  • 需要一些打开/关闭 ISession 管理,而不是基于当前请求

关键是,我在这里看不到单例模式的好处。我们不需要也不提供常见的、请求独立的东西。

我们确实返回取决于请求(及其会话范围)的数据。所以,我建议使用:

.HybridHttpOrThreadLocalScoped()

与逻辑生命周期使用的好处相比,为每个请求创建实例的开销微不足道。

但是,是的,这只是我的建议......因为我看到了许多潜在的问题(锁定、意外更改以及会话中可能提交的脏对象等)

于 2013-06-08T17:33:53.907 回答
1

您必须通过确保每个属性集块都使用锁来使单例线程安全,如下所示:

public int Counter
{
    get { return _counter; }

    set
    {
        lock(_counterLock)
        {
            _counter = value;
        }
    }
}

private int _counter = 0;

private object _counterLock = new Object();
于 2013-06-04T13:51:37.553 回答