1. 程式人生 > 其它 >C# 避免死鎖,使用Monitor.TryEnter方法設定超時時間

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         }

    這樣,即使在兩個執行緒都在互相等待資源的情況下,利用超時機制,依然能夠使他們放棄當前鎖,保證解決死鎖問題。