C# 鎖與死鎖
阿新 • • 發佈:2020-11-30
什麼是死鎖:
所謂死鎖,是指多個程序在執行過程中因爭奪資源而造成的一種僵局,當程序處於這種僵持狀態時,若無外力作用,它們都將無法再向前推進。 因此我們舉個例子來描述,如果此時有一個執行緒A,按照先鎖a再獲得鎖b的的順序獲得鎖,而在此同時又有另外一個執行緒B,按照先鎖b再鎖a的順序獲得鎖。如下
static void LockTooMuch(object lock1, object lock2) { lock (lock1) //鎖定lock1物件 { Thread.Sleep(1000); //執行緒掛起1slock (lock2) //試圖獲取lock2物件的鎖定 { Console.WriteLine("成功獲取到lock2物件的鎖定"); } } } /// <summary> /// 造成一個死鎖 /// </summary> public static void Test() { //定義兩個鎖定物件 objectlock1 = new object(); object lock2 = new object(); //開啟執行緒 Thread t1 = new Thread(() => {LockTooMuch(lock1,lock2); }); t1.Start(); //在主執行緒中鎖定lock2物件 lock (lock2) { Console.WriteLine("這將要產生一個死鎖"); Thread.Sleep(1000); lock (lock1) //試圖訪問lock1 { Console.WriteLine("成功獲取到lock1物件的鎖定"); } } }
通過Monitor的超時鎖定機制避免死鎖
直接使用Monitor類。其擁有TryEnter方法,該方法接受一個超時引數。如果在我們能夠獲取被lock保護的資源之前,超時引數過期,則該方法會返回 false.
/// <summary> /// 使用Monitor避免死鎖 /// </summary> public static void Test2() { //定義兩個鎖定物件 object lock1 = new object(); object lock2 = new object(); //開啟執行緒 Thread t1 = new Thread(() => {LockTooMuch(lock1,lock2); }); t1.Start(); //在主執行緒中使用Monitor類來鎖定lock2物件 //在主執行緒中鎖定lock2物件 lock (lock2) { Console.WriteLine("使用Monitor.TryEnter避免死鎖,有一個超時時間的設定 超時返回false"); Thread.Sleep(1000); //設定5s的超時時間 if(Monitor.TryEnter(lock1,TimeSpan.FromSeconds(5))) { Console.WriteLine("成功獲取到lock1物件的鎖定"); } else { Console.WriteLine("獲取lock1物件失敗,"); } } }
if (Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5))) 這時候是嘗試去獲取lock1,
因為lock1倍分支執行緒給獲取了,那麼獲取不到,這時候等待5秒,5秒後獲取不到就直接走了lese這條路,然後就釋放了lock2,這時候分支執行緒就繼續執行。