多线程中的死锁

时间:2010-08-19 23:26:29

标签: c# multithreading

我试图为死锁创建一个示例。我尝试了以下代码。但它并没有造成僵局,而是像魅力一样。帮助我理解为什么它没有造成死锁。这段代码有什么变化会造成死锁?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ReferenceTypes
{
    class DeadLockExample
    {
        static int a;
        static int b;

        public static void Main(string[] args)
        {
            DeadLockExample.a = 20;
            DeadLockExample.b = 30;

            DeadLockExample d = new DeadLockExample();

            Thread tA = new Thread(new ThreadStart(d.MethodA));
            Thread tB = new Thread(new ThreadStart(d.MethodB));

            tA.Start();
            tB.Start();

            Console.ReadLine();
        }

        private void MethodA()
        {
            lock (this)
            {
                Console.WriteLine(a);
                Thread.Sleep(1000);
                Console.WriteLine(b);
            }
        }

        private void MethodB()
        {
            lock (this)
            {
                Console.WriteLine(b);
                Thread.Sleep(1000);
                Console.WriteLine(a);
            }
        }
     }
}

4 个答案:

答案 0 :(得分:11)

正如其他人所说的那样,两个锁以不同的顺序获得,所以每个人都在等待另一个。我还更改了其中一个Sleep长度,以确保发生死锁的可能性很高。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ReferenceTypes
{
    class DeadLockExample
    {
        static int a;
        static int b;

        static object lockedObjA = new object();
        static object lockedObjB = new object();

        public static void Main(string[] args)
        {
            DeadLockExample.a = 20;
            DeadLockExample.b = 30;

            DeadLockExample d = new DeadLockExample();

            Thread tA = new Thread(new ThreadStart(d.MethodA));
            Thread tB = new Thread(new ThreadStart(d.MethodB));

            tA.Start();
            tB.Start();

            Console.ReadLine();
        }

        private void MethodA()
        {
            lock (DeadLockExample.lockedObjA)
            {
                Console.WriteLine(a);
                Thread.Sleep(1200);

                lock (DeadLockExample.lockedObjB) {
                    Console.WriteLine(b);
                }
            }
        }

        private void MethodB()
        {
            lock (DeadLockExample.lockedObjB)
            {
                Console.WriteLine(b);
                Thread.Sleep(1000);

                lock (DeadLockExample.lockedObjA) {
                    Console.WriteLine(a);
                }
            }
        }
     }
}

答案 1 :(得分:3)

2个锁,2个线程。

线程A获取锁A,休眠然后尝试获取锁B.线程B获取锁B,休眠然后尝试获取锁A,等于死锁。

[线程A必须长时间休眠,以便线程B在线程A尝试获取之前获取锁定B]

答案 2 :(得分:1)

以下3种不同的方法可以导致死锁。这份清单并非详尽无遗。

从锁定部分调用阻止方法。

在这个示例中,线程A获取一个锁,然后立即调用阻塞方法,同时线程B尝试获取相同的锁,但是因为线程A正在等待线程B发出信号之前它被挂起释放锁。

public class Example
{
  ManualResetEvent m_Event = new ManualResetEvent(false);

  void ThreadA()
  {
    lock (this)
    {
      m_Event.WaitOne();
    }
  }

  void ThreadB()
  {
    lock (this)
    {
      m_Event.Set();
    }
  }
}

无序获取两个锁。

这里不需要解释,因为这是一个众所周知的问题。

public class Example
{
  private object m_LockObjectA = new object();
  private object m_LockObjectB = new Object();

  void ThreadA()
  {
    lock (m_LockObjectA) lock (m_LockObjectB) { }
  }

  void ThreadB()
  {
    lock (m_LockObjectB) lock (m_LockObjectA) { }
  }
}

无锁死锁。

这是我最喜欢的死锁插图,因为不涉及锁定或阻塞方法。这个问题的微妙之处足以让那些熟悉线程的人感到困惑。这里的问题与缺乏记忆障碍有关。线程A等待线程B设置信号标志,同时线程B等待线程A重置它,而线程没有看到对方正在进行的更改,因为编译器,JIT和硬件可以自由优化以不直观的方式读取和写入标志。

public class Example
{
  private bool m_Signal = false;

  void ThreadA()
  {
    while (!m_Signal);
    m_Signal = false;
  }

  void ThreadB()
  {
    m_Signal = true;
    while (m_Signal);
  }
}

答案 3 :(得分:0)

来自维基百科 -

  

死锁是两种情况   或者更多的竞争行为   等待对方完成,并且   从来没有。

您没有使用上面的代码满足此要求 - 线程A和线程B都没有等待彼此完成。