Lock statement vs Monitor.Enter method

I do not see any difference between lock statement and Monitor.Enter call.

Look more carefully. The first case copies the reference to a second local variable to ensure that it stays alive.

Notice what the C# 3.0 spec says on the subject:

A lock statement of the form “lock (x) …” where x is an expression of a reference-type, is precisely equivalent to

System.Threading.Monitor.Enter(x);
try { ... }
finally { System.Threading.Monitor.Exit(x); }

except that x is only evaluated once.

It’s that last bit — except that x is only evaluated once — that is the key to the behaviour. In order to ensure that x is evaluated only once we evaluate it once, store the result in a local variable, and re-use that local variable later.

In C# 4 we’ve changed the codegen so that it is now

bool entered = false;
try { 
  System.Threading.Monitor.Enter(x, ref entered);
  ... 
}
finally { if (entered) System.Threading.Monitor.Exit(x); }

but again, x is only evaluated once. In your program you are evaluating the lock expression twice. Your code really should be

    bool lockTaken = false;   
    var temp = test2;
    try {   
        System.Threading.Monitor.Enter(temp, ref lockTaken);   
        test2 = null;   
        Console.WriteLine("Manual collect 3.");   
        GC.Collect();   
        GC.WaitForPendingFinalizers();   
        Console.WriteLine("Manual collect 4.");   
        GC.Collect();   
    }   
    finally {   
       System.Threading.Monitor.Exit(temp);   
    }  

Now is it clear why this works the way it does?

(Also note that in C# 4 the Enter is inside the try, not outside as it was in C# 3.)

Leave a Comment