单例模式如何在 Web 环境中工作?
Posted
技术标签:
【中文标题】单例模式如何在 Web 环境中工作?【英文标题】:How do singleton patterns work in a web context? 【发布时间】:2012-07-06 22:06:48 【问题描述】:所以,使用单例模式的对象只能有一个实例。这在网站上如何运作?
问题:
-
对于网站的每个客户/访问者来说,单例对象是唯一的吗?即单例对象是否每个客户端都有一个实例?
Web 应用程序中的对象仅持续几秒钟,因此如果两个客户端同时访问一个网站,则两个客户端都将尝试创建一个单例对象。这是否意味着会抛出一个访问者会看到的异常?我尝试谷歌搜索,但找不到直接的答案。我只是想澄清一下。
【问题讨论】:
【参考方案1】:史蒂夫,我会尽力回答你的每一个问题:
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 ......许多其他人)。
您需要询问您的同事他们指的是哪种方法,因为这两种方法在某些情况下都有效并且非常常见。
【讨论】:
【参考方案2】:这完全取决于您的单例实现。在这里,我假设您将单例创建为在静态构造函数中初始化的静态字段。
理论上,根据其设置,IIS 可能会为您的应用程序创建多个进程,并且每个进程可以创建多个线程来处理请求。每个进程都有自己的单例,可以共享多个线程(和多个请求)。但是同时在一台服务器上可以有多个“单例”实例(每个进程一个)(但是,如果我理解正确,可以在 IIS 设置中禁止多个进程)。
如果您使用静态构造函数,那么在第一次访问您的类时会以线程安全的方式创建单例。见Is the C# static constructor thread safe?
虽然单例创建是线程安全的,但您仍然必须以线程安全的方式实现单例类的内部。
Singleton 将在您的应用程序进程存在且未重新启动时存在。应用进程的生命周期由 IIS 管理,可以是很长的时间,也可以是很短的时间。
【讨论】:
【参考方案3】:单例由 IIS 维护,因此单例的持续时间与 IIS 应用程序池一样长。一旦它被回收或 IIS 被重置,那么单例就会消失。您需要锁定单例以进行多次访问。就像在任何其他客户端服务器应用程序中一样。
通常我会尽量避免它,因为它有点违背网站本质上是无状态客户端服务器应用程序的想法。为什么不直接使用 Session 来存储任何共享数据?
【讨论】:
我刚开始在一家公司的网络部门实习,无意中听到一些同事在网络环境中谈论单身人士,我很困惑。这不是我目前正在实施的。 如何使用会话存储共享数据?【参考方案4】:对于记录器和共享资源,我们肯定可以在 Web 应用程序中使用单例。正如 Liam 所说,只要您的应用程序池未被清除,它们就会一直存在。
为了更好地理解,请访问...http://www.oodesign.com/singleton-pattern.html
谢谢
【讨论】:
看起来不像一个完整的答案。本来可以更好的评论 down-vote :( 好吧可能不是一个完整的答案,没有人接受,但提出问题的人可以说一个完整或不完整的答案。虽然需要认真【参考方案5】: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;
【讨论】:
所以,有两件事。 1)不能有人只是new MyDbContext()
吗?这并不能阻止两个。 2)我认为你这样做是因为你不想new
一堆相同的上下文,但这最好在你的 IoC 容器中处理以上是关于单例模式如何在 Web 环境中工作?的主要内容,如果未能解决你的问题,请参考以下文章