使用lock(this)来说明死锁的示例代码

Med*_*Man 29 .net c# multithreading deadlock

我读过几篇文章和帖子是说lock(this),lock(typeof(MyType)),lock("a string")都是不好的做法,因为另一个线程可以锁定相同的密钥和导致死锁.为了理解这个问题,我试图创建一些示例代码来说明死锁,但一直无法解决这个问题.

有人可以编写一个简洁的代码来说明这个经典问题吗?请保持简短,我只能在较小的块中消化代码.

编辑: 我认为lassevk总结得很好; 真正的问题是你失去了对锁的控制.一旦发生这种情况,您无法控制锁被调用的顺序,并且您允许潜在的死锁情况.

lock(this),lock(typeof(MyType))等所有的情况下,你选择了一个锁是无法控制的情况.

jal*_*alf 32

只有拥有多个锁时才会出现死锁.您需要一种情况,两个线程都拥有另一个需要的资源(这意味着必须至少有两个资源,并且两个线程必须尝试以不同的顺序获取它们)

这是一个简单的例子:

// thread 1
lock(typeof(int)) {
  Thread.Sleep(1000);
  lock(typeof(float)) {
    Console.WriteLine("Thread 1 got both locks");
  }

}

// thread 2
lock(typeof(float)) {
  Thread.Sleep(1000);
  lock(typeof(int)) {
    Console.WriteLine("Thread 2 got both locks");
  }
}
Run Code Online (Sandbox Code Playgroud)

假设两个线程都在彼此的一秒内启动,那么在任何人进入内部锁之前,他们都有时间抓住第一个锁.如果没有Sleep()调用,其中一个线程很可能有时间在另一个线程开始之前获取并释放两个锁.

  • 啊哈,我在你发布它的同时写了完全相同的样本:)但我选择了long和int (2认同)
  • 非常好的示例:创建死锁的关键因素是锁定**DIFFERENT**订单中的两个资源. (2认同)

Mag*_*his 5

这个想法是,你永远不应该锁定你无法控制谁有权访问的东西。

类型对象是对每段 .net 代码都可见的单例,您无法控制谁从外部锁定您的“this”对象。

对于字符串来说也是如此:由于字符串是不可变的,因此框架只保留“硬编码”字符串的一个实例并将它们放入一个池中(据说该字符串被保留),如果您在代码中写入两次字符串“你好”,你总会得到同样的羞辱。

考虑以下示例:您在超级私有调用中只编写了 Thread1,而 Thread2 由您在后台线程中使用的某个库调用......

void Thread1()
{
  lock (typeof(int))
  {
    Thread.Sleep(1000);
    lock (typeof(long))
      // do something
  }
}

void Thread2()
{
  lock (typeof(long))
  {
    Thread.Sleep(1000);
    lock (typeof(int))
      // do something
  }
}
Run Code Online (Sandbox Code Playgroud)