Can someone please explain me why we need nested locking ?
look at this example :
lock (locker)
lock (locker)
lock (locker)
{
...
}
can someone please explain (+ example will be much appreciated).
Can someone please explain me why we need nested locking ?
look at this example :
lock (locker)
lock (locker)
lock (locker)
{
...
}
can someone please explain (+ example will be much appreciated).
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.
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.
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.
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.