I suppose that this is an interesting code example.
We have a class -- let\'s call it Test -- with a Finalize method. In the
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.)
It is because the reference pointed to by test1
is assigned to the local variable CS$2$0000
in the IL code. You null out the test1
variable in C#, but the lock
construct gets compiled in such a manner that a separate reference is maintained.
It is actually quite clever that the C# compiler does this. Otherwise it would be possible to circumvent the guarentee the lock
statement is supposed to enforce of releasing the lock upon exiting the critical section.