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         }

     

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM