20

In the past I have put a lock around accessing the HttpRuntime.Cache mechanism. I'm not sure if I had really researched the issue in the past and blindy surrounded it with a lock.

Do you think this is really necessary?

Wesley
  • 10,652
  • 4
  • 37
  • 52
Andrew Harry
  • 13,773
  • 18
  • 67
  • 102
  • http://stackoverflow.com/questions/447705/locking-httpruntime-cache-for-lazy-loading seems that the cache is thread safe – Andrew Harry Apr 16 '09 at 03:34

4 Answers4

10

This article suggests a lock should be used:

http://msdn.microsoft.com/en-us/magazine/cc500561.aspx

Quote:

The problem is that if you've got a query that takes 30 seconds and you're executing the page every second, in the time it takes to populate the cache item, 29 other requests will come in, all of which will attempt to populate the cache item with their own queries to the database. To solve this problem, you can add a thread lock to stop the other page executions from requesting the data from the database.

Here is their code snippet:

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

I haven't tested this code, but I would be very interested to hear someone who has evaluated this approach in a production environment.

Mark Avenius
  • 13,679
  • 6
  • 42
  • 50
frankadelic
  • 20,543
  • 37
  • 111
  • 164
  • 11
    I don't think that this is necessary in terms of the caching thread-safety - it's more to prevent multiple accesses to the database to run a potentially expensive query. – zcrar70 Mar 26 '10 at 19:39
  • 5
    Just a small but important gotcha in the example: between the lock(lockObject) and the if (cachedResults == null), the cached item should be retrieved again. See this http://stackoverflow.com/questions/39112/what-is-the-best-way-to-lock-cache-in-asp-net for a proper example. – Ciprian Teiosanu Dec 10 '12 at 17:14
  • @frankadelic the link is broken. – peval27 Mar 07 '17 at 17:47
8

According to this documentation http://msdn.microsoft.com/en-us/library/system.web.caching.cache(VS.80).aspx access to the cache object is thread safe. As for the object(s) you store in the cache thread safety has to come from somewhere else.

j3r03nq
  • 196
  • 5
2

I don't think locking is the answer to the issue below, especially in the production environment, where you have several servers running your application.

The problem is that if you've got a query that takes 30 seconds and you're executing the page every second, in the time it takes to populate the cache item, 29 other requests will come in, all of which will attempt to populate the cache item with their own queries to the database. To solve this problem, you can add a thread lock to stop the other page executions from requesting the data from the database.

Liong Ng
  • 21
  • 1
2

I don't think it's necessary to wrap access to the HttpRuntime.Cache property with a lock, as the .Cache property is static and also thread-safe.

There are many different ways of accessing the Cache object (HttpRuntime.Cache, HttpContext.Current.Cache, Page.Cache etc.). They all access the same Cache object, as there's only one Cache object per Application Domain, as it's effectively a thread-safe Singleton object.

CraigTP
  • 44,143
  • 8
  • 72
  • 99