What's the advantage of Monitor.Enter(object, ref bool) over Monitor.Enter(object)?

c#, c#-3.0, c#-4.0, concurrency

Solution

As always, Eric Lippert has already answered this:

Fabulous Adventures In Coding: Locks and exceptions do not mix

Excerpt:

/* First version of your code, with the Monitor.Enter before the try. */

The problem here is that if the compiler generates a no-op instruction between the monitor enter and the try-protected region then it is possible for the runtime to throw a thread abort exception after the monitor enter but before the try. In that scenario, the finally never runs so the lock leaks, probably eventually deadlocking the program.

In C# 4.0 we’ve changed lock so that it now generates code as if it were

/* Second version of your code, with the Monitor.Enter inside the try. */

The problem now becomes someone else’s problem; the implementation of `Monitor.Enter` takes on responsibility for atomically setting the flag in a manner that is immune to thread abort exceptions messing it up.

Problem

According to the language specification `lock(obj) statement;` would be compiled as: ``` object lockObj = obj; // (the langspec doesn't mention this var, but it wouldn't be safe without it) Monitor.Enter(lockObj); try { statement; } finally { Monitor.Exit(lockObj); } ``` However, it is compiled as: ``` try { object lockObj = obj; bool lockTaken = false; Monitor.Enter(lockObj, ref lockTaken); statement; } finally { if (lockTaken) Monitor.Exit(lockObj); } ``` That seems to be a lot more complicated than necessary. So the question is, what's the advantage of that implementation?

Original source