使用foreach的奇怪的lock()行为

时间:2009-02-19 22:34:04

标签: c# multithreading

所以,这不是我的代码,并且已经缩短以显示行为,但它给出了非常意外的结果。

我在一个类中有两个函数和一个锁

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));
  }
}

现在,我知道这没有意义,但是当调用Func2时,不应该Func1死锁吗?在我们的例子中,它执行。感谢。

3 个答案:

答案 0 :(得分:13)

不,它不应该死锁。

Func1如果被持有锁的人调用(例如Func2

,则可以获得锁定

MSDN doc for lock解释说:

“当保持互斥锁定时,在同一执行线程中执行的代码也可以获取并释放锁定。但是,在锁定释放之前,阻止其他线程中执行的代码获取锁定。”

锁定的目标是防止不同的线程访问相同的资源。 Func1Func2位于相同的主题

答案 1 :(得分:3)

lock语句(封装Monitor类)支持在线程内重新进入(递归),即您可以嵌套使用相同监视器的调用。

其他锁定方法:

  • Monitor - 支持递归
  • ReaderWriterLock - 支持递归,但速度很慢
  • ReaderWriterLockSlim - 支持递归但不鼓励
  • EventHandleManualResetEventAutoResetEventMutexSemaphore) - 不支持递归

答案 2 :(得分:1)

.NET Monitor对象(锁定使用)是递归的,因此持有锁的线程可以自由地再次进入该锁。

(并非所有的锁结构都是递归的,并且可以针对递归支持进行参数化。)