代码之家  ›  专栏  ›  技术社区  ›  SaravananArumugam

多线程中的死锁

  •  7
  • SaravananArumugam  · 技术社区  · 14 年前

    我试图为死锁创建一个例子。我尝试了以下代码。但它非但没有造成僵局,反而发挥了魅力。帮助我理解为什么它没有造成死锁。此代码中的什么更改会导致死锁?

    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 回复  |  直到 14 年前
        1
  •  11
  •   quentin-starin    14 年前

    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);
                    }
                }
            }
         }
    }
    
        2
  •  3
  •   Mitch Wheat    14 年前

    2锁,2螺纹。

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

    [线程A必须睡眠足够长的时间,以便线程B在线程A尝试获取锁B之前获取锁B]

        3
  •  1
  •   Brian Gideon    14 年前

    这里有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);
      }
    }
    
        4
  •  0
  •   Will A    14 年前

    来自维基百科-

    僵局是两个 一个或多个相互竞争的行动 所以从来没有。

    上面的代码不能满足这一要求—线程a和线程B都在等待对方完成这一点是不存在的。