是单身在ASP.NET MVC请求之间自动持久?
-
27-09-2019 - |
题
我有成千上万的整数的查找表(LUT),我就请求基于什么是从数据库中提取计算的东西相当数量的使用。
如果我简单地创建一个标准单保持LUT,是它自动请求之间持续或我特别需要将其推到应用程序状态?
如果它们被自动持续存在,则差值存储它们与应用程序的状态是什么?
如何将一个正确的单身实现是什么样子?它并不需要被延迟初始化,但它需要是线程安全的(千每个服务器实例理论的用户),并有不错的表现。
编辑:乔恩斯基特的第四版本看起来很有希望 http://csharpindepth.com/Articles/General /Singleton.aspx
public sealed class Singleton
{
static readonly Singleton instance=new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
// randomguy's specific stuff. Does this look good to you?
private int[] lut = new int[5000];
public int Compute(Product p) {
return lut[p.Goo];
}
}
解决方案
是,静态成员仍然存在(如不坚持同样的事情 - 这不是“救”,它永远不会消失),其中将包括一个单独的实现。你得到一定程度的暂缓初始化的自由,好像是在一个静态分配或静态构造函数创建的,它不会被调用,直到第一次使用的相关类。默认情况下,这个创作锁,但所有其他用途必须是线程安全的,你说的。由于并发的参与程度,则除非单将是不可变的(你的查表不应用生命周期变化),你必须要非常小心,因为你如何更新(单程是假单 - 在更新您创建一个新的对象,然后锁定起来分配给它来取代当前值,不是严格意义上的单身,虽然它看起来像一个“从外面”)
在大的危险是无状态协议,如网络打交道时任何事情引入全局状态是犯罪嫌疑人,特别是。它可以用来很好虽然,特别是作为永久或接近永久数据的内存中缓存,尤其是当它涉及不容易快速地从数据库中获得一个对象图。
在缺陷是相当大的,虽然,所以要小心。特别是,锁定问题的风险不能被低估。
编辑,到编辑匹配的问题是:
我的大问题将是数组被初始化如何。显然,这个例子是不完整的,因为它只会曾经有0每个项目。如果它获得一套在初始化,并且是只读的,然后罚款。如果它是可变的,则是非常,非常小心你的线程。
另外要注意的上缩放太多这样的查找窗口的负面影响。当你在有预先计算的mosts请求保存,效果是有一段非常繁重的工作时,单被更新。长十岁上下的启动很可能会容忍(因为它不会很频繁),但任意缓慢起伏之后发生的事情可能会非常棘手追查其来源。
其他提示
我不会依赖一个静态的存在坚持请求之间。 [总是有,虽然不太可能,机会,过程将请求之间进行复位。]我推荐的HttpContext对请求之间持续共享资源的Cache对象。
编辑:见乔恩的有关只读锁定
评论这已经有一段时间,因为我已经经历了单身的(我宁愿让我的IOC容器处理寿命),但在这里,你可以如何处理线程安全问题。你需要锁定围绕任何变异单身的状态。只读操作,如您Compute(int)
将不再需要锁定。
// I typically create one lock per collection, but you really need one per set of atomic operations; if you ever modify two collections together, use one lock.
private object lutLock = new object();
private int[] lut = new int[5000];
public int Compute(Product p) {
return lut[p.Goo];
}
public void SetValue(int index, int value)
{
//lock as little code as possible. since this step is read only we don't lock it.
if(index < 0 || index > lut.Length)
{
throw new ArgumentException("Index not in range", "index");
}
// going to mutate state so we need a lock now
lock(lutLock)
{
lut[index] = value;
}
}