为什么我的asp.net代码中多次创建静态对象?

时间:2017-09-28 15:02:51

标签: c# windbg stackexchange.redis

我认为静态对象是跨多个线程共享的。但是,我在我的一个网站上遇到了很高的CPU问题,所以我采取了一个windbg转储并且非常惊讶,我看到了:

enter image description here

我们可以看到有一个名为ConnectionMultiplexer的类的10个实例。但我的代码将ConnectionMultiplexer创建为静态对象。这应该意味着只为所有线程创建一个实例。那么windbg怎么会显示多个实例呢?

这是我创建redis连接的代码

size_t

1 个答案:

答案 0 :(得分:5)

ConnectionMultiplexer实际上是使用新C#7短语法=>的readonly(get)属性。每次访问时都会返回LazyConnection.Value

然后使用LazyThreadSafetyMode.PublicationOnly在MSDN中定义为LazyThreadSafetyMode.ExecutionAndPublication

  

当多个线程尝试初始化Lazy实例时   同时,允许所有线程运行初始化   方法(或默认构造函数,如果没有初始化   方法)。完成初始化的第一个线程设置值   懒惰的例子。该值将返回给其他任何线程   同时运行初始化方法,除非   初始化方法会在这些线程上抛出异常。任何   由竞争线程创建的T的实例是   丢弃。如果初始化方法抛出异常   线程,异常传播出Lazy.Value属性   在那个线程上。该异常未缓存。的价值   IsValueCreated属性仍为false,后续调用   值属性,由抛出异常的线程或   通过其他线程,导致初始化方法再次运行。如果   初始化方法递归访问的Value属性   懒惰的实例,没有抛出任何异常。

这意味着如果多个线程试图在同一时间访问它,它们每个都会创建自己的实例,尽管你最终会使用第一个创建的线程而不管线程(但实例仍然存在)。

您实际需要的是FileSystemPersistentAcceptOnceFileListFilter 但这可能会引入死锁。

如果你不需要这个懒人,你可以使用Jon Skeet在他的书C#In Depth中提出的单例模式实现之一

您可以在https://msdn.microsoft.com/en-us/library/system.threading.lazythreadsafetymode(v=vs.110).aspx

找到它们