Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using lock(obj) inside a recursive call

As per my understanding a lock is not released until the runtime completes the code block of the lock(obj) ( because when the block completes it calls Monitor.Exit(obj).

With this understanding i am not able to understand the reason behind the behaviour of the following code :

private static string obj = "";         private static void RecurseSome(int number)         {             Console.WriteLine(number);             lock (obj)             {                 RecurseSome(++number);             }         } 

//Call: RecurseSome(0)

//Output: 0 1 2 3...... stack overflow exception

There must be some concept that i am missing. Please help.

like image 743
Manish Basantani Avatar asked Mar 09 '10 08:03

Manish Basantani


People also ask

Is C# lock recursive?

The lock statement, Monitor , Mutex , and ReaderWriterLock are all recursive.

How do recursive locks work?

In computer science, the reentrant mutex (recursive mutex, recursive lock) is a particular type of mutual exclusion (mutex) device that may be locked multiple times by the same process/thread, without causing a deadlock.

How do you stop a recursive call?

One way to break out of a recursive function in Python is to throw an exception and catch that at the top level. Some people will say that this is not the right way to think about recursion, but it gets the job done.

How do you stop a recursive function in Java?

The best way to get out of a recursive loop when an error is encountered is to throw a runtime exception.


2 Answers

A lock knows which thread locked it. If the same thread comes again it just increments a counter and does not block.

So, in the recursion, the second call also goes in - and the lock internally increases the lock counter - because it is the same thread (which already holds the lock).

ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_csref/html/656da1a4-707e-4ef6-9c6e-6d13b646af42.htm

Or MSDN: http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

states:

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.

Note the thread references and the emphasis on "ANOTHER" thread.

like image 52
TomTom Avatar answered Sep 29 '22 09:09

TomTom


Please do NOT lock on a string object. This could lead to unexpected behavior such as deadlocks in your application. You are currently locking on the empty string, which is even worse. The whole assembly is using the same empty string. And to make things worse; as an optimization, the CLR reuses strings over AppDomains. Locking on string means you are possibly doing a cross-domain lock.

Use the following code as lock object:

private readonly static object obj = new object(); 

UPDATE

In fact, I think it's safe to say that being allowed to lock on anything is a major design flaw in the .NET framework. Instead, they should have created some sort of SyncRoot sealed class and only allowed the lock statement and Monitor.Enter to accept instances of SyncRoot. This would have saved us a lot of misery. I do understand where this flaw is coming from though; Java has the same design.

like image 28
Steven Avatar answered Sep 29 '22 09:09

Steven