Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interlocking Monitor.Enter and Monitor.Exit blocks

The ECMA-335 specification states the following:

*Acquiring a lock (System.Threading.Monitor.Enter or entering a synchronized method) shall implicitly perform a volatile read operation, and releasing a lock (System.Threading.Monitor.Exit or leaving a synchronized method) shall implicitly perform a volatile write operation. (...)

A volatile read has acquire semantics meaning that the read is guaranteed to occur prior to any references to memory that occur after the read instruction in the CIL instruction sequence. A volatile write has release semantics meaning that the write is guaranteed to happen after any memory references prior to the write instruction in the CIL instruction sequence.*

This means that compilers cannot move statements out of Monitor.Enter/Monitor.Exit blocks, but other statements are not forbidden to be moved into the block. Perhaps, even another Monitor.Enter could be moved into the block (as volatile write followed by a volatile read can be swapped). So, could the following code:

class SomeClass
{
    object _locker1 = new object();
    object _locker2 = new object();

    public void A()
    {
        Monitor.Enter(_locker1);
        //Do something
        Monitor.Exit(_locker1);
        Monitor.Enter(_locker2);
        //Do something
        Monitor.Exit(_locker2);
    }

    public void B()
    {
        Monitor.Enter(_locker2);
        //Do something
        Monitor.Exit(_locker2);
        Monitor.Enter(_locker1);
        //Do something
        Monitor.Exit(_locker1);
    }
}

, be turned into an equivalent of the followig:

class SomeClass
{
    object _locker1 = new object();
    object _locker2 = new object();

    public void A()
    {
        Monitor.Enter(_locker1);
        //Do something
        Monitor.Enter(_locker2);
        Monitor.Exit(_locker1);
        //Do something
        Monitor.Exit(_locker2);
    }

    public void B()
    {
        Monitor.Enter(_locker2);
        //Do something
        Monitor.Enter(_locker1);
        Monitor.Exit(_locker2);
        //Do something
        Monitor.Exit(_locker1);
    }
}

, possibly leading to deadlocks? Or am I missing anything?

like image 872
XanderMK Avatar asked Aug 01 '11 18:08

XanderMK


People also ask

What is Monitor Enter in C#?

Use Enter to acquire the Monitor on the object passed as the parameter. If another thread has executed an Enter on the object but has not yet executed the corresponding Exit, the current thread will block until the other thread releases the object.

What does lock() do in C#?

C# Lock keyword ensures that one thread is executing a piece of code at one time. The lock keyword ensures that one thread does not enter a critical section of code while another thread is in that critical section. Lock is a keyword shortcut for acquiring a lock for the piece of code for only one thread.

How is lock different from Monitor in C#?

CSharp Online Training Both Monitor and lock provides a mechanism that synchronizes access to objects. lock is the shortcut for Monitor. Enter with try and finally. Lock is a shortcut and it's the option for the basic usage.

Does Monitor enter wait?

Wait is the same as Monitor. Enter except that it releases the lock on the object first before reacquiring.


1 Answers

The ECMA-335 spec is a lot weaker than what the CLR (and every other implementation) uses.

I remember reading (heresay) about Microsoft's first attempt to port to IA-64, using a weaker memory model. They had so much of their own code depending on the double-checked locking idiom (which is broken under the weaker memory model), that they just implemented the stronger model on that platform.

Joe Duffy has a great post summarizing the (actual) CLR memory model for us mere mortals. There's also a link to an MSDN article that explains in more detail how the CLR differs from ECMA-335.

I don't believe it's an issue in practice; just assume the CLR memory model, since everyone else does. No one would create a weak implementation at this point, since most code would simply break.

like image 182
Stephen Cleary Avatar answered Oct 29 '22 22:10

Stephen Cleary