In what use cases is locking on ASP.NET cache required/desirable

112 Views Asked by At

When inserting and retrieving items into cache. Is it best practice to perform a lock on the cache. I've following the guidelines from the following post.

What is the best way to lock cache in asp.net?

But i'm keen to get some context on whether i need to lock or not. This is the only location i use this cache.

private static object _tcsLock = new object();

public TcsService()
{

}


public LiveScoreTcs GetScoreCard()
{

    // try to pull from cache here
    var scorecard = HttpContext.Current.Cache[Global.Caching.SecondXILiveScoreKey];
    if (scorecard != null)
    {
        return (LiveScoreTcs)scorecard;
    }

    lock (_tcsLock)
    {
        // cache was empty before we got the lock, check again inside the lock
        scorecard = HttpContext.Current.Cache[Global.Caching.SecondXILiveScoreKey];
        // cache is still empty, so retreive the value here
        if (scorecard == null)
        {
            scorecard = BuildSecondXiLiveScorecard();
            // store the value in the cache here
            if (scorecard != null)
            {
                HttpContext.Current.Cache.Insert(Global.Caching.SecondXILiveScoreKey, scorecard,
                null,
                Global.Caching.AbsoluteExpiration.Tcs,
                Cache.NoSlidingExpiration,
                CacheItemPriority.Default,
                null);
            }
        }

    }

    // return the cached value here
    return (LiveScoreTcs)scorecard;
}
2

There are 2 best solutions below

6
On BEST ANSWER

Locking is not about where in the code you use it but if more than one thread can execute that code at any one time. If there is a chance of a race condition you need to lock, even if apparently in development and your specific setup no errors emerge. This is so because multi-threading is impacted by so many factors that you cannot predict the behavior.

So if this is a multi-threaded application (web server) you need to lock.

Reducing the amount of code that is locked is also a good advice, as collisions put threads into the waiting state you want to make them wait as less as possible.

If you think you have many read accesses and few write accesses you may want to look into more complex mechanisms like Semaphore and adopt a Multiple Reader Single Writer pattern.

Really, it all depends on what you do in the rest of the application (threads or parallel web requests).

6
On

If you don't use the lock as you've done than you have the potential to end up re-creating the object you're going to cache multiple times. In some circumstances that's a major problem, particularly if doing the work causes side effects which are important to not perform multiple times, and in some cases doing the work multiple times wastes a bit of time, and is a bit less performant, which may or may not be something you need to avoid.

So whether or not it's okay to ensure BuildSecondXiLiveScorecard is never executed more than once until it expires from the cache is something we can't say, but that's the only potential concern with not having the lock.