我认为静态对象是跨多个线程共享的。但是,我在我的一个网站上遇到了很高的CPU问题,所以我采取了一个windbg转储并且非常惊讶,我看到了:
我们可以看到有一个名为ConnectionMultiplexer的类的10个实例。但我的代码将ConnectionMultiplexer创建为静态对象。这应该意味着只为所有线程创建一个实例。那么windbg怎么会显示多个实例呢?
这是我创建redis连接的代码
size_t
答案 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
找到它们