Home > .NET Framework > Critical Sections of code – Monitor

Critical Sections of code – Monitor

Consider that you are writing a Logger library. Assume this logs contents to a file. Initial design of the library is something like this:
public class Logger {
    private static StreamWriter writer;
    static Logger() {
        // read fileName from config or something else
        writer = new StreamWriter(fileName);
    }
    public static void Log(string source, string category, string message) {
        writer.WriteLine("—————————————————————————-");
        writer.WriteLine("Source: " + source);
        writer.WriteLine("Date & Time: " + DateTime.Now.ToString("dd/MM/yyyy HH:mm"));
        writer.WriteLine("Category: " + category);
        writer.WriteLine("Message: " + message);
        writer.WriteLine("—————————————————————————-");
    }
}
Let us say that this logger is going to used by a single threaded application. Things will work fine. Assume the same logger is now distributed to a multi-threaded application. 
Thread A calls logger with "Source: BusinessLayer – ClaimsProcessor", "Category: Warning", "Message: Blah Blah Blah"
Thread B calls logger with "Source: DataLayer – ClaimsProcessor", "Category: Error", "Message: Something serious has happenned"
 
Thread A

Thread B

writes the source

Suspended

Context-Switch

Context-Switch

Suspended

writes the source

Context-Switch

Context-Switch

writes the datetime

Suspended

Context-Switch

Context-Switch

Suspended

writes the datetime

Context-Switch

Context-Switch

writes the Category

Suspended

Context-Switch

Context-Switch

Suspended

writes the Category

Context-Switch

Context-Switch

writes the message

Suspended

Context-Switch

Context-Switch

Suspended

writes the message

Context-Switch

Context-Switch

The result will be messy due to the out of order execution.

How do you avoid this data corruption?

This can be avoided if we can ensure that only one thread executes this ‘critical section’ of code at a time. Assoicate this section of code with a lock object. Lock the object. Execute this section of code. Release the lock. If another thread tries to acquire a lock it has to wait till the this thread releases a lock. This can be achieved in .NET using the Monitor class. Let us rewrite the code using the Monitor class.

 

public class Logger {
    private static StreamWriter writer;
    static Logger() {
        // read fileName from config or something else
        writer = new StreamWriter(fileName);
    }
    public static void Log(string source, string category, string message) {
        try {
            Monitor.Enter(writer);
            writer.WriteLine("—————————————————————————-");
            writer.WriteLine("Source: " + source);
            writer.WriteLine("Date & Time: " + DateTime.Now.ToString("dd/MM/yyyy HH:mm"));
            writer.WriteLine("Category: " + category);
            writer.WriteLine("Message: " + message);
            writer.WriteLine("—————————————————————————-");
        }
        finally {
           Monitor.Leave(writer);
        }
    }
}
 
We have associated the ciritcal section of code with the lock by the calling Monitor.Enter.
Monitor.Leave releases the lock. We have this code in finally as we need the lock to be released even in the case of exceptions. When a thread calls Monitor.lock passing the writer object. The framework checks if the witer object is locked already. If it is not this thread acquires the lock. Else this thread goes into wait till the writer object is released.
 
The above pattern of code is so common in the framework that the languages C#, VB.NET support them using the lock and SyncLock blocks repectively.
 
lock(someObject) {
    // Execute Critical Section of code
}
 
exapnds to
 
try {
    Monitor.Enter(someObject);
    // Execute Critical Section of code
}
finally {
    Monitor.Leave(someObject);
}
A monitor cannot be used to synchronize access across processes. The same has to be done using Mutex if it has to be across processes.

Advertisements
Categories: .NET Framework
  1. No comments yet.
  1. November 19, 2010 at 10:59 pm
  2. November 19, 2010 at 11:09 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: