C#中的死锁和解决方案

https://blog.csdn.net/weixin_44228698/article/details/108672903

C#中的死锁和解决方案

  1. 在多任务系统下,当一个或多个进程等待系统资源,而资源又被进程本身或其它进程占用时,就形成了死锁。总的来说,就是两个线程,都需要获取对方锁占有的锁,才能够接着往下执行,但是这两个线程互不相让,你等我先释放,我也等你先释放,但谁都不肯先放,就一直在这僵持住了。
  2. 死锁的演示
        static void Main(string[] args)
        {
            Task.Run(()=> Method1());
            Task.Run(() => Method2());
            Console.Read();
        }
        static void Method1()
        {
            lock (obj1)
            {
                Console.WriteLine("开始执行方法一");
                Thread.Sleep(1000);
                lock (obj2)
                {
                    Console.WriteLine("方法一执行完毕");
                }
            }
        }
        static void Method2()
        {
            lock (obj2)
            {
                Console.WriteLine("开始执行方法二");
                Thread.Sleep(1000);
                lock (obj1)
                {
                    Console.WriteLine("方法二执行完毕");
                }
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

结果如下,这两个方法永远都不会执行完毕
C#中的死锁和解决方案
3.那么,死锁应该怎么样解决呢?

  • 首先,应该尽量避免大量嵌套的锁的使用,这也是预防为主,当然也有信号量也可能会造成死锁,这样的话只能靠程序员自身注意去避免了。
  • 如果需要使用嵌套锁,可以使用锁的超时机制来避免对资源的长时间占用,演示如下:
        private static readonly object obj1 = new object();
        private static readonly object obj2 = new object();
        static void Main(string[] args)
        {
            Task.Run(()=> Method1());
            Task.Run(() => Method2());
            Console.Read();
        }
        static void Method1()
        {
            try
            {
                if (Monitor.TryEnter(obj1, 5000))
                {
                    Console.WriteLine("开始执行方法一");
                    Thread.Sleep(1000);
                    bool locked = false;
                    try
                    {
                        Monitor.TryEnter(obj2, 5000, ref locked);
                        Console.WriteLine("方法一执行完毕");
                    }
                    finally
                    {
                        if (locked)
                        {
                            Monitor.Exit(obj2);
                        }
                    }
                }
            }
           finally
            {
                Monitor.Exit(obj1);
            }
        }
        static void Method2()
        {
            try
            {
                if (Monitor.TryEnter(obj2, 5000))
                {
                    Console.WriteLine("开始执行方法二");
                    Thread.Sleep(1000);
                    bool locked=false;
                    try
                    {
                        Monitor.TryEnter(obj1, 5000,ref locked);
                        Console.WriteLine("方法二执行完毕");
                    }
                    finally
                    {
                        if (locked)
                        {
                            Monitor.Exit(obj1);
                        }
                    }
                }
            }
            finally
            {
                Monitor.Exit(obj2);
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

C#中的死锁和解决方案
这样,即使在两个线程都在互相等待资源的情况下,利用超时机制,依然能够使他们放弃当前锁,保证解决死锁问题。

上一篇:安装脚本(.run)文件制作步骤


下一篇:CentOS 8 按tab键不能自动补全问题解决方案