过去,我锁定了访问 HttpRuntime.Cache 机制。我不确定我过去是否真的研究过这个问题并且盲目地用锁包围了它。
你觉得这真的有必要吗?
本文建议应使用锁:
http://msdn.microsoft.com/en-us/magazine/cc500561.aspx
引用:
问题是,如果您有一个需要 30 秒的查询,并且您每秒都在执行该页面,那么在填充缓存项所需的时间内,将会有 29 个其他请求进入,所有这些请求都将尝试填充缓存项与他们自己对数据库的查询。为了解决这个问题,您可以添加一个线程锁来阻止其他页面执行从数据库中请求数据。
这是他们的代码片段:
// check for cached results
object cachedResults = ctx.Cache["PersonList"];
ArrayList results = new ArrayList();
if (cachedResults == null)
{
// lock this section of the code
// while we populate the list
lock(lockObject)
{
cachedResults = ctx.Cache["PersonList"];
// only populate if list was not populated by
// another thread while this thread was waiting
if (cachedResults == null)
{
cachedResults = ...
ctx.Cache["PersonList"] = cachedResults;
}
}
}
我没有测试过这段代码,但我很想听听有人在生产环境中评估过这种方法。
根据此文档http://msdn.microsoft.com/en-us/library/system.web.caching.cache(VS.80).aspx访问缓存对象是线程安全的。至于您存储在缓存中的对象,线程安全必须来自其他地方。
我认为没有必要用锁来包装对 HttpRuntime.Cache 属性的访问,因为 .Cache 属性是静态的并且也是线程安全的。
访问 Cache 对象的方式有很多种(HttpRuntime.Cache、HttpContext.Current.Cache、Page.Cache 等)。它们都访问同一个 Cache 对象,因为每个应用程序域只有一个 Cache 对象,因为它实际上是一个线程安全的 Singleton 对象。
我不认为锁定是下面问题的答案,尤其是在生产环境中,您有多个服务器运行您的应用程序。
问题是,如果您有一个需要 30 秒的查询,并且您每秒都在执行该页面,那么在填充缓存项所需的时间内,将会有 29 个其他请求进入,所有这些请求都将尝试填充缓存项与他们自己对数据库的查询。为了解决这个问题,您可以添加一个线程锁来阻止其他页面执行从数据库中请求数据。