ReaderWriterLockSlim 類 表示用於管理資源訪問的鎖定狀態,可實現多線程讀取或進行獨占式寫入訪問。 使用 ReaderWriterLockSlim 來保護由多個線程讀取但每次只采用一個線程寫入的資源。 ReaderWriterLockSlim 允許多個線程均處於讀取模式,允許一個線程處於寫入模式並獨占鎖定狀態,同時還允許一個具有讀取權限的線程處於可升級的讀取模式,在此模式下線程無需放棄對資源的讀取權限即可升級為寫入模式。 注意 ReaderWriterLockSlim 類似於 ReaderWriterLock,只是簡化了遞歸、升級和降級鎖定狀態的規則。 ReaderWriterLockSlim 可避免多種潛在的死鎖情況。 此外,ReaderWriterLockSlim 的性能明顯優於 ReaderWriterLock。 建議在所有新的開發工作中使用 ReaderWriterLockSlim。 以上引用自MSDN ps:該類在.NET3.5中提供,如需要在2.0中使用請換ReaderWriterLock,用法差不多改了寫方法名,MSDN中說ReaderWriterLockSlim性能比較高 主要屬性,方法 屬性: IsReadLockHeld 獲取一個值,該值指示當前線程是否已進入讀取模式的鎖定狀態。 IsWriteLockHeld 獲取一個值,該值指示當前線程是否已進入寫入模式的鎖定狀態。 方法: EnterReadLock 嘗試進入讀取模式鎖定狀態。 ExitReadLock 減少讀取模式的遞歸計數,並在生成的計數為 0(零)時退出讀取模式。 EnterWriteLock 嘗試進入寫入模式鎖定狀態。 ExitWriteLock 減少寫入模式的遞歸計數,並在生成的計數為 0(零)時退出寫入模式。 當然還有其他很多方法,比如EnterUpgradeableReadLock進入可以升級到寫入模式的讀取模式.. 不過我需要封裝的對象相對來說較為簡單,所以不需要用這些額外的方法和屬性,有興趣的可以自己去研究下 應用 來對比一個老式的lock寫法 private object _Lock = new object(); private void Read() { lock (_Lock) { //具體方法實現 } } private void Write() { lock (_Lock) { //具體方法實現 } } 讀寫鎖分離 private ReaderWriterLockSlim _LockSlim = new ReaderWriterLockSlim(); private void Read() { try { _LockSlim.EnterReadLock(); //具體方法實現 } finally { _LockSlim.ExitReadLock(); } } private void Write() { try { _LockSlim.EnterWriteLock(); //具體方法實現 } finally { _LockSlim.ExitWriteLock(); } } 看上下2種寫法: 從性能的角度來說,肯定是讀寫鎖分離更好了,特別是大多數場合(讀取操作遠遠多余寫入操作) 從可讀性和代碼美觀度來說,就是上面的lock要簡潔的多了,維護起來也更清晰 所以我希望重新封裝ReaderWriterLockSlim,當然我第一想到的就是using了,利用using語法糖的特性封裝一個新的對象 封裝 Code平台: UsingLock 由於是利用的using的語法,所以我直接取名叫UsingLock,簡單好記 UsingLock源碼 方法: Read() 進入讀取鎖定模式 Write() 進入寫入鎖定模式 另外我還加入2個額外的屬性 Data UsingLock中可以保存一個數據,由當前線程中的環境判斷是否可以讀取或設置該對象 Enabled 是否啟用當前組件..這個有妙用,下面介紹 使用場合 MyQueue 我這裡假設了一個隊列系統,把最容易出現問題的修改集合和枚舉集合2個操作公開出來,方便在多線程中測試效果 以下為測試代碼: static void Main(string[] args) { //建立一個字符串集合,總數為1000 List<string> list = new List<string>(1000); for (int i = 0; i < list.Capacity; i++) { list.Add("字符串:" + i); } MyQueue mq = new MyQueue(list); //保存最後一個值,等下用於做比較 string last = list[list.Count - 1]; //開啟1000個線程,同時執行LootFirst方法,並打印出結果 for (int i = 0; i < list.Capacity; i++) { ThreadPool.QueueUserWorkItem(o => { Console.WriteLine(mq.LootFirst()); }); } //在主線程中不停調用mq的遍歷方法,這樣的操作是很容易出現線程爭搶資源的,如果沒有鎖定訪問機制,就會出現異常 while (mq.Count > 0) { foreach (var item in mq) { //如果最後一個值還在,就輸出 "還在" if (item == last) { Console.WriteLine("還在"); } } } }