【问题标题】:Creating a deadlock创建死锁
【发布时间】:2011-10-20 11:50:03
【问题描述】:

我有一些如下所示的代码。这会造成死锁吗?

private readonly object objectLock = new object();

public void MethodA()
{
    lock(objectLock)
    {
       MethodB();
    }
}

public void MethodB()
{
    lock(objectLock)
    {
      //do something
    }
}

更新:将有 2 个线程在运行

【问题讨论】:

    标签: c# .net multithreading c#-4.0 deadlock


    【解决方案1】:

    不 - 但这是:

    private readonly object objectLockA = new object();
    private readonly object objectLockB = new object();
    
    public void MethodA()
    {
        lock(objectLockA)
        {
        lock(objectLockB)
        {
           //...
        }
        }
    }
    
    public void MethodB()
    {
        lock(objectLockB)
        {
        lock(objectLockA)
        {
          //do something
        }
        }
    }
    

    如果您并行调用这两种方法(来自 2 个不同的线程),那么您会遇到死锁...

    【讨论】:

      【解决方案2】:

      不,这不是死锁。它在同一个同步对象上锁定同一个线程。线程可以采用嵌套锁。它只需要释放它等于没有。次。

      【讨论】:

      • 如果 MethodA 调用 MethodB 两次怎么办。那还可以吗?
      • 是的,它仍然可以。你试过了吗?死锁将挂起所有涉及死锁的线程。单线程不能出现死锁。你的应用中是否有多个线程?
      • @Jon 即使那样它也不会导致死锁。这是他们锁定的同一个同步对象。
      • 感谢您的帮助。非常感谢
      • @Jon: MethodB 当然是在同一个线程中由MethodA 调用的。仍然没有死锁。
      【解决方案3】:

      不,您需要两个锁对象来启用死锁。

      【讨论】:

        【解决方案4】:

        如果这是唯一涉及的互斥锁,则不是。同一个线程可以多次锁定同一个互斥体,只要解锁次数相同。

        调用MethodA 在同一线程上产生以下操作序列:

        • 锁定objectLock
        • 致电MethodB
        • 锁定objectLock
        • 解锁objectLock
        • 退出MethodB
        • 解锁objectLock

        所以,objectLock 被锁定两次,两次解锁,但没有死锁:

        • 如果另一个线程尝试调用MethodA,它只会在第一个锁上阻塞,但不会死锁。
        • 如果调用MethodB,也会发生同样的情况。
        • 如果第一个线程调用MethodB,然后其他线程调用MethodA,则会再次发生“正常”阻塞,但不会出现死锁。

        【讨论】:

          【解决方案5】:

          如果复制粘贴以下行,编译并运行,控制台中不会打印“never called”。

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          using System.Threading;
          using System.Threading.Tasks;
          
          namespace deadlocktest
          {
              class Program
              {
              static object object1 = new object();
              static object object2 = new object();
          
              public static void FunctionOne()
              {
                  lock (object1)
                  {
                      Console.WriteLine("FunctionOne called 1");
                      Thread.Sleep(1000);
                      lock (object2)
                      {
                          Console.WriteLine("FunctionOne called 2, never called");
                      }
                  }
              }
          
              public static void FunctionTwo()
              {
                  lock (object2)
                  {
                      Console.WriteLine("FunctionTwo called 1");
                      Thread.Sleep(1000);
                      lock (object1)
                      {
                          Console.WriteLine("FunctionTwo called 2, never called");
                      }
                  }
              }
          
              static void Main(string[] args)
              {
          
                  Thread thread1 = new Thread(FunctionOne);
                  Thread thread2 = new Thread(FunctionTwo);
                  thread1.Start();
                  thread2.Start();
                  int i = 0;
                  while (i < 9)
                  {
                      Console.WriteLine("How bad thread!");
                      i++;
                  }
                  thread1.Join();
                  thread2.Join();
                  Console.ReadLine();
              }
          }
          

          }

          【讨论】:

            猜你喜欢
            • 2012-09-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-25
            • 1970-01-01
            相关资源
            最近更新 更多