HttpRuntime.Cache最佳实践

20

过去,我曾经在访问 HttpRuntime.Cache 机制时设置了锁。我不确定自己以前是否真正研究过这个问题,盲目地围绕它设置了锁。

你认为这样做确实有必要吗?


看起来缓存是线程安全的,无需加锁进行懒加载。 - Andrew Harry
4个回答

10

这篇文章建议使用锁:

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;
    }
  }
}

我并没有测试过这段代码,但我非常希望能听取一些在生产环境下测试过该方法的人的评价。


11
我认为这并非出于缓存线程安全的必要性,而更多是为了防止多次访问数据库以运行潜在昂贵的查询。 - zcrar70
5
在这个例子中有一个小但重要的问题:在 lock(lockObject) 和 if (cachedResults == null) 之间,应该再次检索缓存项。请参考 https://dev59.com/z3VD5IYBdhLWcg3wQJOT 获取一个正确的示例。 - Ciprian Teiosanu
@frankadelic,链接已经失效。 - peval27

8

2

我认为没有必要使用锁来包装对HttpRuntime.Cache属性的访问,因为.Cache属性是静态的且线程安全的。

有很多不同的方式可以访问缓存对象(HttpRuntime.Cache、HttpContext.Current.Cache、Page.Cache等)。它们都访问同一个缓存对象,因为每个应用程序域只有一个缓存对象,它实际上是一个线程安全的单例对象。


2
我认为在以下问题中锁定并不是答案,特别是在生产环境中,你有多个服务器运行你的应用程序。
问题在于,如果你有一个需要30秒的查询,并且你每秒执行一次页面,在填充缓存项所需的时间内,会有29个其他请求进来,所有这些请求都将尝试使用自己的查询填充缓存项。为了解决这个问题,你可以添加一个线程锁,以阻止其他页面执行从数据库请求数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接