C# 为什么在asp.net代码中多次创建静态对象?
我认为静态对象是跨多个线程共享的。然而,我的一个站点出现了高CPU问题,因此我进行了windbg转储,非常惊讶地发现: 我们可以看到一个名为ConnectionMultiplexer的类有10个实例。但我的代码将ConnectionMultiplexer创建为静态对象。这意味着只能为所有线程创建一个实例。那么windbg为什么会显示多个实例呢 这是我创建redis连接的代码C# 为什么在asp.net代码中多次创建静态对象?,c#,windbg,stackexchange.redis,C#,Windbg,Stackexchange.redis,我认为静态对象是跨多个线程共享的。然而,我的一个站点出现了高CPU问题,因此我进行了windbg转储,非常惊讶地发现: 我们可以看到一个名为ConnectionMultiplexer的类有10个实例。但我的代码将ConnectionMultiplexer创建为静态对象。这意味着只能为所有线程创建一个实例。那么windbg为什么会显示多个实例呢 这是我创建redis连接的代码 public static class CacheConnection { private st
public static class CacheConnection
{
private static StackExchangeRedisCacheClient _newconnectionDb;
public static StackExchangeRedisCacheClient NewConnectionDb
=> _newconnectionDb ?? (_newconnectionDb = NewRedisConnection());
private static IDatabase _connectionDb;
public static IDatabase ConnectionDb => _connectionDb ?? (_connectionDb = RedisConnection());
private static StackExchangeRedisCacheClient NewRedisConnection()
{
var serializer = new NewtonsoftSerializer();
return new StackExchangeRedisCacheClient(Connection, serializer);
}
private static IDatabase RedisConnection()
{
var cacheDatabase = Connection.GetDatabase();
return cacheDatabase;
}
public static ConnectionMultiplexer Connection => LazyConnection.Value;
private static readonly Lazy<ConnectionMultiplexer> LazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(
System.Configuration.ConfigurationManager.AppSettings["CacheConnectionString"]), LazyThreadSafetyMode.PublicationOnly);
}
公共静态类缓存连接
{
私有静态StackExchangeDiscacheClient\u newconnectionDb;
公共静态堆栈ExchangeDiscacheClient新连接DB
=>_newconnectionDb??(_newconnectionDb=NewRedisConnection());
私有静态IDatabase_connectionDb;
公共静态IDatabase ConnectionDb=>_ConnectionDb??(_ConnectionDb=RedisConnection());
私有静态StackExchangeDiscacheClient NewRedisConnection()
{
var serializer=newnewtonsoftserializer();
返回新的StackExchangeDiscacheClient(连接、序列化程序);
}
私有静态IDatabase重新连接()
{
var cacheDatabase=Connection.GetDatabase();
返回缓存数据库;
}
公共静态连接多路复用器连接=>LazyConnection.Value;
private static readonly Lazy Lazy connection=new Lazy(()=>ConnectionMultiplexer.Connect(
System.Configuration.ConfigurationManager.AppSettings[“CacheConnectionString]”),LazyThreadSafetyMode.PublicationOnly);
}
ConnectionMultiplexer
实际上是一个只读(get)属性,使用新的C#7短语法=>每次访问时返回LazyConnection.Value
然后使用LazyThreadSafetyMode.PublicationOnly
,它在MSDN()中定义为
当多个线程尝试初始化惰性实例时
同时,允许所有线程运行初始化
方法(或默认构造函数,如果没有初始化
方法)。完成初始化的第一个线程设置
懒惰的实例。该值将返回给执行以下操作的任何其他线程
正在同时运行初始化方法,除非
初始化方法在这些线程上抛出异常。任何
由竞争线程创建的T实例包括
丢弃的。如果初始化方法在任何
线程,异常将从Lazy.Value属性传播出去
在那条线上。该异常未缓存。价值
IsValueCreated属性保持为false,随后调用
值属性,由引发异常的线程或
通过其他线程,使初始化方法再次运行。如果
初始化方法递归地访问
惰性实例,不会引发任何异常
这意味着,如果多个线程试图同时访问它,它们将各自创建自己的实例,尽管不管线程是什么,最终都会使用创建的第一个实例(但实例仍然存在)
您实际需要的是LazyThreadSafetyMode.ExecutionAndPublication
但这可能会导致僵局
如果你不需要这样做,你可以使用Jon Skeet在他的书C#Depth中建议的一种单例模式实现
关于第一句话,你可以在这里找到它们:堆上有任何对象,堆对任何线程都可用。因此,它是静态的这一事实与此无关。