程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 讓C#輕松實現讀寫鎖分離--封裝ReaderWriterLockSlim

讓C#輕松實現讀寫鎖分離--封裝ReaderWriterLockSlim

編輯:C#入門知識

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("還在");             }         }     } }  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved