我有一个包含大量动态内容的 ASP.NET 应用程序。属于特定客户端的所有用户的内容都是相同的。为了减少每个请求所需的数据库命中次数,我决定缓存客户端级数据。我创建了一个静态类(“ClientCache”)来保存数据。
迄今为止,该类最常用的方法是“GetClientData”,它返回一个 ClientData 对象,其中包含特定客户端的所有存储数据。但是,ClientData 是延迟加载的:如果请求的客户端数据已经缓存,则调用者获取缓存的数据;否则,获取数据,添加到缓存中,然后返回给调用者。
最终,我开始在将 ClientData 对象添加到缓存的行的 GetClientData 方法中出现间歇性崩溃。这是方法体:
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null)
_clients = new Dictionary<Guid, ClientData>();
ClientData client;
if (_clients.ContainsKey(fk_client))
{
client = _clients[fk_client];
}
else
{
client = new ClientData(fk_client);
_clients.Add(fk_client, client);
}
return client;
}
异常文本总是类似于“已存在具有相同键的对象”。当然,我尝试编写代码,以便如果客户端已经存在,则无法将其添加到缓存中。
在这一点上,我怀疑我有一个竞争条件并且该方法同时执行了两次,这可以解释代码是如何崩溃的。但是,我感到困惑的是,该方法如何可以同时执行两次。据我所知,任何 ASP.NET 应用程序一次只能处理一个请求(这就是我们可以使用 HttpContext.Current 的原因)。
那么,这个错误是否可能是一个需要在关键部分加锁的竞争条件?还是我错过了一个更明显的错误?