Channels ▼


Synchronizing Access to the ASP.NET Cache

Devised to extend the capabilities of the Application intrinsic object, the Cache object lacks one key feature that the now old-fashioned Application object supplies-the ability to execute a bunch of update statements atomically. Already in classic ASP, the Application object provides a pair of methods to lock and unlock the object, thus serializing access to it. Both Application and Cache are global application objects subject to the action of all possible threads active at a given time. In ASP.NET, both Application and Cache objects are thread-safe, meaning that their contents can be freely accessed by any threads in the AppDomain. However, this applies only to operations that read or write an individual item. The ASP.NET Cache and Application objects guarantee that no other concurrently running threads can ever interfere with the single read or write operation you're executing. However, if you need to execute multiple operations on the Cache object in an atomic way, that's a different story. Consider the following code snippet:

int counter = -1;
object o = Cache["Counter"];
if (o == null)
    // Retrieve the last good known value from a database
    // or return a default value
    counter = RetrieveLastKnownValue();
    counter = (int) Cache["Counter"];
    counter ++;
    Cache["Counter"] = counter;

The Cache object is accessed repeatedly in the context of an atomic operation-incrementing a counter. While individual accesses to Cache are thread-safe, there's no guarantee that other threads won't kick in between the various calls. If there's potential contention on the cached value, you should consider using additional locking constructs, such as the C# lock statement on the Cache object. In Visual Basic .NET, the C# lock statement is implemented through the SyncLock keyword.

Where should you put the lock? If you directly lock the Cache object, you might run into serious troubles. ASP.NET uses the Cache object extensively and doing so might have an impact on the overall performance of the application. If you look under the hood of the Cache object implementation, though, you realize that most of the time, ASP.NET doesn't internally access the cache store via the Cache object. Rather, it accesses the direct data container, which is an internal class named CacheSingle (or CacheMultiple if your application is configured to run in web garden mode).

In this regard, a lock on the Cache object probably won't affect many native ASP.NET components. However, it's still a risk because you might block a bunch of HTTP modules and handlers in the pipeline, as well as other pages and sessions in the application that need to use cache entries. Note that by locking the Cache object, you prevent access to the whole Cache contents and not just to the entries you need to protect from concurrent access.

The best way out seems to be using a synchronizer, which is an intermediate but global object that you lock before entering in a piece of code that is sensitive to concurrency:

    // Access the Cache here.

This pattern must be replicated for each access to the cache that requires serialization. The synchronizer object must be global to the application. For example, it could be a static member defined in the global.asax file and initialized in the Application_Start event.

Dino Esposito is Wintellect's ADO.NET and XML expert, and a trainer and consultant based in Rome, Italy. Dino is a contributing editor to Windows Developer Network and MSDN Magazine, and the author of several books for Microsoft Press including Building Web Solutions with ASP.NET and ADO.NET and Applied XML Programming for .NET. Contact Dino at [email protected].

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.