Re-Entrant Locks in C#

Re-entrant locks in C#

No, not as long as you are locking on the same object. The recursive code effectively already has the lock and so can continue unhindered.

lock(object) {...} is shorthand for using the Monitor class. As Marc points out, Monitor allows re-entrancy, so repeated attempts to lock on an object on which the current thread already has a lock will work just fine.

If you start locking on different objects, that's when you have to be careful. Pay particular attention to:

  • Always acquire locks on a given number of objects in the same sequence.
  • Always release locks in the reverse sequence to how you acquire them.

If you break either of these rules you're pretty much guaranteed to get deadlock issues at some point.

Here is one good webpage describing thread synchronisation in .NET: http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/

Also, lock on as few objects at a time as possible. Consider applying coarse-grained locks where possible. The idea being that if you can write your code such that there is an object graph and you can acquire locks on the root of that object graph, then do so. This means you have one lock on that root object and therefore don't have to worry so much about the sequence in which you acquire/release locks.

(One further note, your example isn't technically recursive. For it to be recursive, Bar() would have to call itself, typically as part of an iteration.)

What is the correct way to prevent reentrancy and ensure a lock is acquired for certain operations?

There is one synchronization object in .NET that isn't re-entrant, you are looking for a Semaphore.

Before you commit to this, do get your ducks in a row and ask yourself how it can be possible that BeginProcess() can be called again on the same thread. That is very, very unusual, your code has to be re-entrant for that to happen. This can normally only happen on a thread that has a dispatcher loop, the UI thread of a GUI app is a common example. If this is truly possible and you actually use a Semaphore then you'll get to deal with the consequence as well, your code will deadlock. Since it recursed into BeginProcess and stalls on the semaphore. Thus never completing and never able to call EndProcess(). There's a good reason why Monitor and Mutex are re-entrant :)

Why doesn't Lock'ing on same object cause a deadlock?

For the same thread a lock is always reentrant, so the thread can lock an object as often as it wants.

Lock aqcuired and further attempts to lock do not block: are C# locks re-entrant?

Locks in .NET are reentrant. Only acquisitions from other threads are blocked. When the same thread locks the same object multiple times, it simply increments a counter, and decrements it when released. When the counter hits zero, the lock is actually released for access from other threads.

Best match in C# to Java ReentrantLock and Condition?

I think what you're looking for is the static Monitor class. I allows for blocking and non-blocking mutex acquisition, as well as condition variable operations. (They call them Pulse, PulseAll and Wait rather than signal and await).

C# Lock Statement

Monitor (which is used by the lock statement under the covers) is reentrant, so it's technically ok for the same thread to lock on an object multiple times. The lock will be released when the outer lock scope completes. However, reentrant locks are difficult to reason about and should be avoided unless you have no other option.

Deadlocks do not occur due to reentrant locks. They occur when you take out locks on multiple objects while some other thread locks the same objects in a different order.

Recursive / nested locking in C# with the lock statement

Yes, locks based on Monitor in .NET are recursive, and counted.

From the docs for Monitor.Enter:

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.

Whether this is a good thing or not is up for debate...



Related Topics



Leave a reply



Submit