第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)
一. 監視鎖(Monitor和lock)
1. Monitor類,限定線程個數的一把鎖(Synchronized lock是他的語法糖),兩個核心方法:
Enter:鎖住某個資源。
Exit:退出某一個資源。
測試案例:開啟5個線程同時對一個變量進行自增操作,結果變量有序的輸出,說明該鎖同時只允許一個線程訪問。
但是寫法很麻煩,每次都要try-catch-finally,還要聲明bool變量。這個時候lock語法糖就很好的解決了這個問題。
?代碼實踐:
?
1 static object lockMe = new object();2 {3 for (int i = 0; i < 5; i++)4 {5 Task.Factory.StartNew(() =>6 {7 for (int j = 0; j < 100; j++)8 {9 var b = false; 10 try 11 { 12 Monitor.Enter(lockMe, ref b); 13 Console.WriteLine(num++); 14 } 15 catch (Exception) 16 { 17 18 throw; 19 } 20 finally 21 { 22 if (b) 23 { 24 Monitor.Exit(lockMe); 25 } 26 } 27 28 } 29 30 }); 31 } 32 }2. lock語法糖
使用很簡單,聲明一個靜態的object類型變量,調用lock語法糖,將共享變量放入其中,即可保證lock內同時只能一個線程訪問。
?代碼實踐:
1 {2 for (int i = 0; i < 5; i++)3 {4 Task.Factory.StartNew(() =>5 {6 for (int j = 0; j < 100; j++)7 {8 lock (lockMe)9 { 10 Console.WriteLine(num++); 11 } 12 } 13 }); 14 } 15 }?
?
二. 混合鎖
1. 簡介:混合鎖=用戶模式鎖+內核模式鎖,先在用戶模式下內旋,如果超過一定的閾值,會切換到內核鎖,在內旋模式下,我們會看到大量的Sleep(0),Sleep(1),Yield等語法。
Thread.Sleep(1) 讓線程休眠1ms
Thread.Sleep(0) 讓線程放棄當前的時間片,讓本線程更高或者同等線程得到時間片運行。
Thread.Yield() 讓線程立即放棄當前的時間片,可以讓更低級別的線程得到運行,當其他thread時間片用完,本thread再度喚醒。
混合鎖包括以下三種:ManualResetEventSlim、SemaphoreSlim、ReaderWriterLockSlim,這三種混合鎖,要比他們對應的內核模式鎖?(ManualResetEvent、Semaphore、ReaderWriterLock),的性能高的多。
2. ManualResetEventSlim
構造函數默認為false,可以使用Wait方法替代WaitOne方法,支持任務取消. (詳細的代碼同內核版本類似,這里不做測試了)
3. SemaphoreSlim
用法和內核版本類似,使用Wait方法代替WaitOne方法,Release方法不變。(詳細的代碼同內核版本類似,這里不做測試了)
4. ReaderWriterLockSlim
用法和內核版本類似,但是四個核心方法換成了:
鎖讀的兩個核心方法:EnterReadLock、ExitReadLock。
鎖寫的兩個核心方法:EnterWriteLock、ExitWriteLock。
(詳細的代碼同內核版本類似,這里不做測試了)
?
總結
以上是生活随笔為你收集整理的第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#进阶之WebAPI(三)
- 下一篇: 信用卡不良信用记录保存几年