5

Can someone please explain me why we need nested locking ?

look at this example :

lock (locker)
  lock (locker)
    lock (locker)
      {
        ...
      }

enter image description here

can someone please explain (+ example will be much appreciated).

Royi Namir
  • 144,742
  • 138
  • 468
  • 792

4 Answers4

13

Can someone please explain me why we need nested locking ?

It is only an issue because you might have nested (eg mutually recursive) calls to methods that need to lock. Those methods must allow being called with the resource already locked but they can not depend on it. So nested locking is allowed, not needed.

The code you posted (and the book you refer to) show how it works by reducing it to an inline scenario. That is not 'real' code.

The simple rule is that a thread that already owns a lock can lock it again and that the number of Exits must match the number of Enters to release the lock.

H H
  • 263,252
  • 30
  • 330
  • 514
  • im reading abook about threading. and there is a sepcial chapter for it which i dont understnad and so i ask. http://books.google.co.il/books?id=VENrFSQFco8C&pg=PA813&lpg=PA813&dq=%22A+thread+can+repeatedly+lock+the+same+object+in+a+nested+(reentrant)+fashion%22&source=bl&ots=3uU4rnd_9P&sig=5NNh4Jbi7pVEZrLydrrs_bOhsBc&hl=en&sa=X&ei=qQbPT5zGNorV8gP0q424DA&ved=0CC0Q6AEwAQ#v=onepage&q=%22A%20thread%20can%20repeatedly%20lock%20the%20same%20object%20in%20a%20nested%20(reentrant)%20fashion%22&f=false – Royi Namir Jun 06 '12 at 07:29
  • unless you're nesting different locks... but that is not the case in OPs example... – Daren Thomas Jun 06 '12 at 07:30
  • 3
    @RoyiNamir From the book: "A thread *can* repeatedly lock the same object in a nested (reentrant) fashion", meaning you are allowed, but not required, to lock a mutex multiple times. – univerio Jun 06 '12 at 07:32
  • 1
    @Henk Holterman: probabbly *recursive* is not correct definition. More correct would be to say nested call (where recursion is a custom case) – Tigran Jun 06 '12 at 07:32
  • @Tigran - you're right, but the main point is it always requires 2 methods that always need to lock. – H H Jun 06 '12 at 07:34
  • @univerio i know i can . the question talkes about usages ." when will i need to do nested locking" – Royi Namir Jun 06 '12 at 07:42
  • 1
    @HenkHolterman so if one methods calls the other and both have locks - so the thread **will** be able to access the second method ( which also has a lock) because it is the _same thread_ **and** the _same obj locked_ ? – Royi Namir Jun 06 '12 at 08:05
  • 1
    @RoyiNamir - Yes, that is the essence and the purpose of nested locking. – H H Jun 06 '12 at 08:07
  • @henk thanks. final question. if method2 has already a queue of waiting threads. and suddenly our thread come to the method2. will he be in ? (while other threads are already waiting ) – Royi Namir Jun 06 '12 at 08:11
  • A method does not have a queue but the locker object does. And yes, when a thread already has the lock it can lock again even if others are waiting. – H H Jun 06 '12 at 08:27
  • 1
    In POSIX threads, the "purpose" of re-entrant locking was that someone dared the team to do it, and it ended up being left in. In other frameworks the purpose is that people will complain about the lack of re-entrant locks rather than fix their code to not need them. – Jon Hanna Aug 18 '12 at 17:37
5

There are situations whether the ability to nest locks on the same thread is very practical.

Suppose you have a class with multiple methods. Suppose you want to have a very simple locking scheme like this:

class A
{
    public void MethodOne()
    {
        using (locker)
        {
            ...body...
        }
    }

    public void MethodTwo()
    {
        using (locker)
        {
            ...body...
        }
    }
}

Now, if MethodOne calls MethodTwo, you would have a deadlock at the beginning of MethodTwo, if there wasn't a reentrant locking capability in the monitor. The thread would simply have blocked itself through the locker.

Fortunately, this example just works in .NET. The locker "knows" which thread has locked it and how many times and it will let (only) the owning thread through. The count is used to make sure that the unlock from the perspective of other waiting threads happens only when exiting MethodOne rather than when exiting MethodTwo. So this is an example of useful nested locking.

On the other hand, the example mentioned in the question seems to come from this book. The authors wanted to make it clear that nested locking is possible in .NET, automatically; but their example code is contrived and not intended to appear in anyone's code except when trying to learn how locking works under the hood.

Jirka Hanika
  • 13,301
  • 3
  • 46
  • 75
  • 1
    in the case mentioned, method two would wait for method one to release its lock, but method one wouldn't release the lock until method two completed => deadlock – Nathan Jun 06 '12 at 07:40
  • @Nathan can you **append** to the answer the solution of which nested lock solve this problem ? – Royi Namir Jun 06 '12 at 07:41
  • if the lock monitor checks for a nested lock request, the lock request will succeed and therefore won't block (which is what causes the deadlock). Does that make sense? – Nathan Jun 06 '12 at 07:46
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/12184/discussion-between-nathan-and-royi-namir) – Nathan Jun 06 '12 at 07:50
2

The direct answer to your question is: you don't need nested locking. However, the compiler allows it in order to make certain scenarios easier to code.

In the sample code from the question, the inner locks will always succeed - because in order to get to the inner lock, you must already have succeeded in obtaining the outer lock. Your thread already has a lock on locker and so the inner lock "automatically" succeeds.

This is never necessary and provides no extra thread safety.

However, in scenarios such as those posted in Jirka Hanika's answer, this behaviour means that one thread-safe member can be called by another thread-safe member without having to worry about deadlocks.

Dan Puzey
  • 33,626
  • 4
  • 73
  • 96
1

You don't need nested locking at all as you mention.

But it's worth pointing out for the sake of clarity that some locks can be nested. Check out ReaderWriterLockSlim class, where you enter as a read lock and then within that scope, you may upgrade it to a write lock.

EDIT: As Royi Namir points out, calling nested functions each of which has it's own lock, will conceptually produce the aforementioned scenario, but the way the question is posed, it looks like 3 locks are being done in the same scope, one after each other which makes less sense.

Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • http://books.google.co.il/books?id=VENrFSQFco8C&pg=PA813&lpg=PA813&dq=%22A+thread+can+repeatedly+lock+the+same+object+in+a+nested+(reentrant)+fashion%22&source=bl&ots=3uU4rnd_9P&sig=5NNh4Jbi7pVEZrLydrrs_bOhsBc&hl=en&sa=X&ei=qQbPT5zGNorV8gP0q424DA&ved=0CC0Q6AEwAQ#v=onepage&q=%22A%20thread%20can%20repeatedly%20lock%20the%20same%20object%20in%20a%20nested%20(reentrant)%20fashion%22&f=false – Royi Namir Jun 06 '12 at 07:30