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.
The lock statement, Monitor , Mutex , and ReaderWriterLock are all recursive.
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.
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.
The best way to get out of a recursive loop when an error is encountered is to throw a runtime exception.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With