一. 監視鎖(Monitor和lock)函數
1. Monitor類,限定線程個數的一把鎖,兩個核心方法:性能
Enter:鎖住某個資源。測試
Exit:退出某一個資源。spa
測試案例:開啓5個線程同時對一個變量進行自增操做,結果變量有序的輸出,說明該鎖同時只容許一個線程訪問。線程
可是寫法很麻煩,每次都要try-catch-finally,還要聲明bool變量。這個時候lock語法糖就很好的解決了這個問題。3d
代碼實踐:code
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語法糖 blog
使用很簡單,聲明一個靜態的object類型變量,調用lock語法糖,將共享變量放入其中,便可保證lock內同時只能一個線程訪問。資源
代碼實踐:it
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。
(詳細的代碼同內核版本相似,這裏不作測試了)