22

所以,一个使用单例模式的对象只能有一个实例。这在网站上如何工作?

问题:

  1. 单例对象对网站的每个客户/访问者来说都是唯一的吗?即单例对象每个客户端都获得一个实例吗?
  2. Web 应用程序中的对象仅持续几秒钟,因此如果两个客户端同时访问一个网站,则两个客户端都将尝试创建一个单例对象。这是否意味着会抛出一个访问者会看到的异常?我尝试谷歌搜索,但找不到直接的答案。我只是想澄清一下。
4

5 回答 5

9

史蒂夫,我会尽力回答你的每一个问题:

1) 对于 Web 开发,将对象限定为 Web 请求是很常见的(有时这也称为“每个请求上下文”或“每个 http 上下文”),但我们通常不将这些称为单例那个确切的原因。事实上,大多数 IOC 容器都内置了一个开箱即用的“每个 Web 请求”范围以及一个“单例”。

2) Web 应用程序有时也有真正的单例(由所有请求访问)是很常见的。如上所述,这并不完全正确,因为它将被限定在应用程序池中,并且在/如果重新启动应用程序池时会被吹走。但对于 Web 应用程序而言,这是一个单例。正如 Jigar 所提到的,有时以这种方式设置诸如日志记录等“横切关注点”。这些通常不会在每个 Web 请求中初始化,而是在 global.asax 中或依靠 IOC 容器为您执行此操作。您只需确保在执行对​​象创建时使用标准锁定模式之一来防止两个线程/客户端/等...同时创建对象。这是来自 Microsoft 的链接,但也有其他实现: http://msdn.microsoft.com/en-us/library/ff650316.aspx 如果您使用的是流行的 IOC 容器之一,它将为您解决这个问题(Structuremap、Windsor、Autofac、Unity、Ninject...和许多其他人)。

您需要询问您的同事他们指的是哪种方法,因为这两种方法在某些情况下都有效并且非常常见。

于 2012-07-06T13:17:39.513 回答
2

这完全取决于您的单例实现。在这里,我假设您将单例创建为在静态构造函数中初始化的静态字段。

理论上,根据其设置,IIS 可能会为您的应用程序创建多个进程,并且每个进程可以创建多个线程来处理请求。每个进程都有自己的单例,可以共享多个线程(和多个请求)。但是同时在一台服务器上可以有多个“单例”实例(每个进程一个)(但是,如果我理解正确,可以在 IIS 设置中禁止多个进程)。

如果您使用静态构造函数,那么将在第一次访问您的类时以线程安全的方式创建单例。请参阅C# 静态构造函数线程是否安全?

但是,尽管单例创建是线程安全的,但您仍然必须以线程安全的方式实现单例类的内部。

当您的应用程序进程存在且未重新启动时,单例将存在。应用程序进程的生命周期由 IIS 管理,因此它可以是很长的时间,也可以是很短的时间。

于 2012-07-06T13:18:19.243 回答
1

单例由 IIS 维护,因此单例只持续与 IIS 应用程序池一样长。一旦它被回收或 IIS 被重置,那么单例就会消失。您需要锁定单例以进行多次访问。就像您在任何其他客户端服务器应用程序中一样。

一般来说,我会尽量避免它,因为它有点违背网站本质上是无状态客户端服务器应用程序的想法。为什么不直接使用 Session 来存储任何共享数据呢?

于 2012-07-06T12:42:25.467 回答
0

对于记录器和共享资源,我们肯定可以在 Web 应用程序中使用单例。正如 Liam 所提到的,只要您的应用程序池没有被清除,它们就会一直存在。

为了更好地理解,请访问...http://www.oodesign.com/singleton-pattern.html

谢谢

于 2012-07-06T12:44:54.560 回答
-1
public class SingletonContext<TContext>
    where TContext: DbContext,new()
{
    private static TContext _context;

    private SingletonContext()
    {

    }
    public static TContext GetInstance()
    {
        if (_context == null)
        {
            _context = new TContext();
        }
        return _context;
    }

}
于 2018-02-08T08:15:04.983 回答