What does a lock statement do under the hood?

391,678

Solution 1

The lock statement is translated by C# 3.0 to the following:

var temp = obj;

Monitor.Enter(temp);

try
{
    // body
}
finally
{
    Monitor.Exit(temp);
}

In C# 4.0 this has changed and it is now generated as follows:

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    // body
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(temp); 
    }
}

You can find more info about what Monitor.Enter does here. To quote MSDN:

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. It is legal for the same thread to invoke Enter more than once without it blocking; however, an equal number of Exit calls must be invoked before other threads waiting on the object will unblock.

The Monitor.Enter method will wait infinitely; it will not time out.

Solution 2

Its simpler than you think-

According to Microsoft: The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released.

The lock keyword calls Enter at the start of the block and Exit at the end of the block. lock keyword actually handles Monitor class at back end.

For example:

private static readonly Object obj = new Object();

lock (obj)
{
    // critical section
}

In the above code, first the thread enters a critical section, and then it will lock obj. When another thread tries to enter, it will also try to lock obj, which is already locked by the first thread. Second thread will have to wait for the first thread to release obj. When the first thread leaves, then another thread will lock obj and will enter the critical section.

Solution 3

No, they are not queued, they are sleeping

A lock statement of the form

lock (x) ... 

where x is an expression of a reference-type, is precisely equivalent to

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

You just need to know that they are waiting to each other, and only one thread will enter to lock block, the others will wait...

Monitor is written fully in .net so it is enough fast, also look at class Monitor with reflector for more details

Solution 4

Locks will block other threads from executing the code contained in the lock block. The threads will have to wait until the thread inside the lock block has completed and the lock is released. This does have a negative impact on performance in a multithreaded environment. If you do need to do this you should make sure the code within the lock block can process very quickly. You should try to avoid expensive activities like accessing a database etc.

Solution 5

The performance impact depends on the way you lock. You can find a good list of optimizations here: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

Basically you should try to lock as little as possible, since it puts your waiting code to sleep. If you have some heavy calculations or long lasting code (e.g. file upload) in a lock it results in a huge performance loss.

Share:
391,678
NLV
Author by

NLV

Web Two O.

Updated on July 08, 2022

Comments

  • NLV
    NLV almost 2 years

    I see that for using objects which are not thread safe we wrap the code with a lock like this:

    private static readonly Object obj = new Object();
    
    lock (obj)
    {
        // thread unsafe code
    }
    

    So, what happens when multiple threads access the same code (let's assume that it is running in a ASP.NET web application). Are they queued? If so how long will they wait?

    What is the performance impact because of using locks?

  • LukeH
    LukeH almost 13 years
    Note that the code emitted for the lock statement changed slightly in C#4: blogs.msdn.com/b/ericlippert/archive/2009/03/06/…
  • LukeH
    LukeH almost 13 years
    But trying to write low-lock code can often result in subtle, hard-to-find-and-fix bugs, even if you're an expert in the field. Using a lock is often the lesser of two evils. You should lock exactly as much as you need to, no more, no less!
  • supercat
    supercat over 10 years
    @LukeH: There are some usage patterns where low-lock code can be very simple and easy [do { oldValue = thing; newValue = updated(oldValue); } while (CompareExchange(ref thing, newValue, oldValue) != oldValue]. The biggest danger is that if the requirements evolve beyond what such techniques can be handle, it may be hard to adapt the code to handle that.
  • Mohanavel
    Mohanavel over 10 years
    @ArsenMkrt, they are not kept in "Blocked" state "Queue?. I think there are some difference between Sleep and block state, is not it?
  • Arsen Mkrtchyan
    Arsen Mkrtchyan over 10 years
    what difference you mean @Mohanavel?
  • Aiden Strydom
    Aiden Strydom about 10 years
    According to MSDN "Using the lock (C#) or SyncLock (Visual Basic) keyword is generally preferred over using the Monitor class directly, both because lock or SyncLock is more concise, and because lock or SyncLock insures that the underlying monitor is released, even if the protected code throws an exception. This is accomplished with the finally keyword, which executes its associated code block regardless of whether an exception is thrown." msdn.microsoft.com/en-us/library/ms173179.aspx
  • priehl
    priehl over 9 years
    What's the point of the var temp = obj; line. since it's just a ref to begin with, what good does making another one do?
  • Steven
    Steven over 9 years
    @priehl It allows the user to change obj without the whole system to deadlock.
  • Joy George Kunjikkuru
    Joy George Kunjikkuru about 8 years
    Just another syntactic sugar?
  • Steven
    Steven about 8 years
    @Joymon eventually, every language feature is syntactic sugar. Language features are about about making developers more productive and making applications more maintainable, as is the lock feature as well.
  • Emil
    Emil over 7 years
    should we create a dummy object to lock or can we lock an existing variable in the context?
  • Umar Abbas
    Umar Abbas over 7 years
    @batmaci - Locking on a separate private dummy object gives you a guarantee that no one else is locking in that object. If you lock on the data and that same piece of data is visible to the outside you lose that guarantee.
  • Alex
    Alex almost 7 years
    Does this mean that if you use the same "object" for the lock in different methods, no matter what method a thread hits, if there is another thread executing another method with the same "object" used in the lock, the thread has to wait until the "object" is released? I appreciate your time.
  • Dizzy H. Slightly Voided
    Dizzy H. Slightly Voided almost 7 years
    Correct. This is the entire purpose of the lock-statement and Monitor: so that you can perform an operation in one thread without having to worry about another thread mucking it up.
  • jstuardo
    jstuardo almost 7 years
    What happens if more than one process is waiting for the lock to release? Are the waiting processes queued so that they will be lock the critical section in FIFO order?
  • jstuardo
    jstuardo almost 7 years
    What happens if more than one process is waiting for the lock to release? Are the waiting processes queued so that they will be lock the critical section in FIFO order?
  • Arsen Mkrtchyan
    Arsen Mkrtchyan almost 7 years
    @jstuardo, lock or monitor is not visible outside of process... it make sense only for threads in the single process... for processes Mutex, Semaphore or other Windows Core objects can be used...
  • jstuardo
    jstuardo almost 7 years
    That was not the question. The question was regarding "lock" keyword. Suppose a process enter a "lock" section. That means that process blocks that piece of code and no other process may be able to enter that section until that lock is released. Well.... now, 2 more processes try to enter the same block. Since it is protected by "lock" keyword, they will wait, according to what was said in this forum. When the first process releases the lock. What process enters the block? the first one that tried to enter or the last one?
  • Arsen Mkrtchyan
    Arsen Mkrtchyan almost 7 years
    I guess you mean thread instead of process... if so, than the answer is No, there is no guarantee which one will enter... more here stackoverflow.com/questions/4228864/…
  • CarenRose
    CarenRose about 5 years
    Link has broken.
  • Umar Abbas
    Umar Abbas over 4 years
    @jstuardo - They are queued, but the order is not guaranteed to be FIFO. Check out this link: albahari.com/threading/part2.aspx
  • Martijn Pieters
    Martijn Pieters over 4 years
    Copied without attribution from net-informations.com/faq/qk/lock.htm