3

I'm writing a global error handler/logger for applications running in Windows Azure. When an error occurs in the application, a number of operations are performed that need to happen atomically. I need to prevent an error from being logged until the previous one has completed. Meanwhile, I want reads of the logs to occur as needed.

My initial thought was using a Monitor/lock and lock only the error writes. That way the reads aren't inhibited at all. I was wondering though whether a ReaderWriterLockSlim would be more appropriate. I can't say I truly understand the value between one approach vs. the other.

Should I create a ReaderWriterLockSlim and do something like the following below (with reads being wrapped in EnterReadLock)...

public static void LogError(Exception exception)
{
    _lock.EnterWriteLock();

    ...

    _lock.ExitWriteLock();
}

Or do I simply do something like the following, only locking the write sections:

public static void LogError(Exception exception)
{
     lock (someStaticLock)
     {
        ...
     }
}

Any thoughts/advice would be much appreciated.

Heshan Perera
  • 4,592
  • 8
  • 44
  • 57
Jonathan Carter
  • 1,029
  • 1
  • 9
  • 17
  • It is my understanding that ReaderWriterLockSlim is mainly for high-performance applications where there's a lot of lock contention. Exceptions are - well - exceptional, so I would just use plain old locks for this. – 500 - Internal Server Error Mar 04 '11 at 00:57

3 Answers3

4

OK, it entirely depends on how resource contention is expected. Following is a simple decision I would make based on what I'm locking and how much locking.

ReaderWriterLockSlim is implemented using a spinlock, therefore if you have long locking resources (writing text in this case) it would lead to a worse performance because of spinning by waiting threads. That said, its very useful tool in following situations.

  • If you have a lot of locks and each of them is finer grained (locks for very small pieces of code) then ReaderWriterLockSlim or (spinlock).
  • Number of threads or contentions expected is high spinlock makes sense provided locking is fine grained.

Lock or Monitor is best suited when your contentions are coarsegrained and you know that contentions or number of locks are lower.

ReaderWriterLockSlim is comparatively faster than ReaderWriterLock atleast 3-5 times.

Sanjeevakumar Hiremath
  • 10,985
  • 3
  • 41
  • 46
  • 1
    For even more finer locking `Interlocked Functions` are best suited. Have a look at this [MSDN article](http://msdn.microsoft.com/en-us/magazine/cc163715.aspx#S8) – Sanjeevakumar Hiremath Mar 04 '11 at 01:27
  • So if I use a lock would I only need to lock the writes? Or would I lock the reads too? I'd definitely like to prevent reading bad data. – Jonathan Carter Mar 04 '11 at 02:21
  • If you dont mind dirty reads you dont have to lock reads. If you want your reads always contain complete log of last write then yes you'd have to lock. – Sanjeevakumar Hiremath Mar 04 '11 at 02:23
  • I wouldn't recommend using Interlocked operations to anyone who didn't have some serious experience with parallel programming and knew exactly what they were doing. Interlocked algorithms can be infamously bastardly to debug. – Martin Mar 04 '11 at 03:43
4

Why don't you use a Queue to store the exceptions as they occur and spit them out in a background worker thread? Then you can just lock the enqueue/dequeue on each side. The window for collisions can be kept fairly small, and it's okay if your actual writing of the log data is behind, because order is preserved. If you want, you can wrap the Exception in some collection that includes the timestamp of when the item was enqueued so you can timestamp them appropriately.

dviljoen
  • 1,612
  • 1
  • 16
  • 28
0

Well, I think you shouldn't read without a lock on it, because you can read while the atomic operation are in course. The ReaderWriterLock seems better, as it garantees that no reader can enter when there's a write in process.

Tiago Ribeiro
  • 217
  • 1
  • 3