Monday, December 5, 2011

Monitor.Enter/Monitor.Exit - Threading



Monitor.Enter and Monitor.Exit provides exclusive locking and ensures only one thread enters inside monitor block at a time. Lock statement internally uses Monitor.Enter and Monitor.Exit with try/finally block.

public class MyClass
{
       static int a=12, b=4;
       static object obj =new Object();
       public static void Divide()
       {
              Monitor.Enter(obj);
              try {
                     if (b != 0)
                           Console.WriteLine("{0} / {1} = {2}", a, b, a/b);
                     b = 0;
              }
              finally
              {
                     Monitor.Exit(obj);
              }
       }
       public static void Main()
       {
              Thread t1 = new Thread(new ThreadStart(Divide));
              t1.Start();
       }
}


As demonstrated in above code, when one thread enters Monitor.Enter block, other threads are trying to enter inside block at same time are queued in ready queue until first thread call Monitor.exit statement similar to lock statement.

In some scenario with multithreaded application, once Monitor.Enter acquires lock and due to some exception not able to enter try/finally block in this case lock will not be released and cause memory leaked. Dotnet 4.0 has the solution for the same, added overload Monitor.Enter method. It takes referenced boolean value along with locked object. If lock is acquired, the overloaded boolean value returns true. Let’s see how it works.

static int a = 12, b = 4;
static object obj = new Object();
static bool isLocked = false;
public static void Divide()
{
    Monitor.Enter(obj,ref isLocked);
    try
    {
        if (b != 0)
            Console.WriteLine("{0} / {1} = {2}", a, b, a / b);
        b = 0;
    }
    finally
    {
        if (isLocked)
        {
            Monitor.Exit(obj);
        }
    }
}

As per above code if lock is acquired successfully then isLocked variable's value set to true and we can release lock if isLocked value is true. If lock is not acquired isLocked value remains false.



See Also - 

1 comment: