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