views:

137

answers:

3

Hi everyone,

So, this isn't my code and has been shortened to show the behavior, but it is giving very unexpected results.

I have two function in a class and a lock

object mylock = new object();
List<string> temp = new List<string>();

Func1(string)
{
  lock(mylock)
  {
    temp.Add(string);
  }
}

Func2()
{
  lock(mylock)
  {
    temp.ForEach(p => Func1(p));
  }
}

Now, I know this makes no sense, but when Func2 is called, shouldn't Func1 deadlock? In our case, it executes. Thanks.

+12  A: 

No, it shouldn't deadlock.

Func1 can get the lock if it's called by someone that already holds the lock (like Func2)

The MSDN doc for lock explains:

"While a mutual-exclusion lock is held, code executing in the same execution thread can also obtain and release the lock. However, code executing in other threads is blocked from obtaining the lock until the lock is released."

The goal of lock is to prevent different threads from accessing the same resource. Func1 and Func2 are on the same thread.

Daniel LeCheminant
func1 is most definitely getting that lock, because I'm stepping through it in the debugger. The class is actually a singleton (I know, I know...), so I know there is only one instance of the class. I don't understand what's going on...
Steve
@Steve. Right, that's what I said. Func1 can get the lock, because it is being called by Func2, which has the lock.
Daniel LeCheminant
sorry, I read that totally wrong. Thanks for the help.
Steve
+1  A: 

.NET Monitor objects (which lock uses) are recursive, so a thread holding the lock can enter that lock again freely.

(Not all locking constructs are recursive, and arguments can be made against recursive support.)

Richard
Makes sense, but I didn't know that...
Spence
+1  A: 

The lock statement (encapsulating the Monitor class) supports re-entrance (recursion) within a thread, i.e. you can nest the calls, which use the same monitor.

Other locking approachs:

  • Monitor - recursion is supported
  • ReaderWriterLock - recursion is supported, but slow
  • ReaderWriterLockSlim - recursion is supported, but discouraged
  • EventHandle (ManualResetEvent, AutoResetEvent, Mutex, Semaphore) - recursion not supported
Michael Damatov