Synchronizing ASP.NET MVC action methods with ReaderWriterLockSlim
- by James D
Any obvious issues/problems/gotchas with synchronizing access (in an ASP.NET MVC blogging engine) to a shared object model (NHibernate, but it could be anything) at the Controller/Action level via ReaderWriterLockSlim?
(Assume the object model is very large and expensive to build per-request, so we need to share it among requests.)
Here's how a typical "Read Post" action would look. Enter the read lock, do some work, exit the read lock.
public ActionResult ReadPost(int id)
{
// ReaderWriterLockSlim allows multiple concurrent writes; this method
// only blocks in the unlikely event that some other client is currently
// writing to the model, which would only happen if a comment were being
// submitted or a new post were being saved.
_lock.EnterReadLock();
try
{
// Access the model, fetch the post with specificied id
// Pseudocode, etc.
Post p = TheObjectModel.GetPostByID(id);
ActionResult ar = View(p);
return ar;
}
finally
{
// Under all code paths, we must release the read lock
_lock.ExitReadLock();
}
}
Meanwhile, if a user submits a comment or an author authors a new post, they're going to need write access to the model, which is done roughly like so:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveComment(/* some posted data */)
{
// try/finally omitted for brevity
_lock.EnterWriteLock();
// Save the comment to the DB, update the model to include the comment, etc.
_lock.ExitWriteLock();
}
Of course, this could also be done by tagging those action methods with some sort of "synchronized" attribute... but however you do it, my question is is this a bad idea?
ps. ReaderWriterLockSlim is optimized for multiple concurrent reads, and only blocks if the write lock is held. Since writes are so infrequent (1000s or 10,000s or 100,000s of reads for every 1 write), and since they're of such a short duration, the effect is that the model is synchronized , and almost nobody ever locks, and if they do, it's not for very long.