• C# 避免死锁,使用Monitor.TryEnter方法设定超时时间


    1.在多任务系统下,当一个或多个进程等待系统资源,而资源又被进程本身或其它进程占用时,就形成了死锁。总的来说,就是两个线程,都需要获取对方锁占有的锁,才能够接着往下执行,但是这两个线程互不相让,你等我先释放,我也等你先释放,但谁都不肯先放,就一直在这僵持住了。

    2.死锁演示:

     1         static void Main(string[] args)
     2         {
     3             Task.Run(()=> Method1());
     4             Task.Run(() => Method2());
     5             Console.Read();
     6         }
     7         static void Method1()
     8         {
     9             lock (obj1)
    10             {
    11                 Console.WriteLine("开始执行方法一");
    12                 Thread.Sleep(1000);
    13                 lock (obj2)
    14                 {
    15                     Console.WriteLine("方法一执行完毕");
    16                 }
    17             }
    18         }
    19         static void Method2()
    20         {
    21             lock (obj2)
    22             {
    23                 Console.WriteLine("开始执行方法二");
    24                 Thread.Sleep(1000);
    25                 lock (obj1)
    26                 {
    27                     Console.WriteLine("方法二执行完毕");
    28                 }
    29             }
    30         }

    结果如下,这两个方法永远都不会执行完毕。

    3.那么,死锁应该怎么样解决呢?

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

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

    本文来自博客园,作者:云辰,转载请注明原文链接:https://www.cnblogs.com/yunchen/p/14900265.html

  • 相关阅读:
    C语言实现mq收发数据的函数
    4G通信模块在ARM平台下的应用
    4G 通信模块在ARM 平台下的应用
    修改web前端访问端口
    从零开始用 Flask 搭建一个网站(一)
    Python实现Windows定时关机
    前端和后端的数据交互(jquery ajax+python flask+mysql)
    python开源项目及示例代码
    Django读取Mysql数据并显示在前端
    C++关于string的一些用法
  • 原文地址:https://www.cnblogs.com/yunchen/p/14900265.html
Copyright © 2020-2023  润新知