[C#.NET][Thread] 執行緒單一寫入 / 多讀取資源鎖定 – ReaderWriterLock

  • 10705
  • 0
  • 2013-08-16

[C#.NET][Thread] 執行緒單一寫入 / 多讀取資源鎖定 – ReaderWriterLock

ReaderWriterLock 類別,它允許同時間讓執行緒進行讀取,讓一條執行緒進行寫入,如果執行緒不常寫入,大部份的時間都在讀取,那使用它的效能會優於Monitor。

1.AcquireReaderLock 方法進入讀取鎖定,ReleaseReaderLock 方法解除讀取鎖定。
2.AcquireWriterLock 方法進入寫入鎖定,ReleaseWriterLock 方法解除寫入鎖定。

ReaderWriterLock 會保存讀取器鎖定和寫入器鎖定,但它們不會同時執行,我們來由下列的程式碼觀察:

		   1: private static ReaderWriterLock _rw = new ReaderWriterLock(); 
		   2: private static string _writer = "Empty"; 
		   3: private static List<Thread> _WriterThreads = new List<Thread>(); 
		   4: private static List<Thread> _ReaderThreads = new List<Thread>(); 
		   5: static void Main(string[] args) 
		   6: { 
		   7:     for (int i = 0; i < 10; i++) 
		   8:     { 
		   9:         Thread reader = new Thread(new ThreadStart(Reader));//開10隻讀取器 
		  10:         reader.Start(); 
		  11:         if (i < 2)//開2隻寫入器 
		  12:         { 
		  13:             Thread writer = new Thread(new ThreadStart(Writer)); 
		  14:             writer.Start(); 
		  15:         } 
		  16:     } 
		  17:  
		  18:     Console.WriteLine("Main thread exist"); 
		  19:     Console.ReadKey(); 
		  20: } 
		  21:  
		  22: public static void Reader() 
		  23: { 
		  24:     try 
		  25:     { 
		  26:         _rw.AcquireReaderLock(Timeout.Infinite); 
		  27:         Thread t = Thread.CurrentThread; 
		  28:         Console.WriteLine("Thread[{0}]:{1},Read Value is {2}", t.ManagedThreadId, t.ThreadState, _writer); 
		  29:         Thread.Sleep(1000); 
		  30:     } 
		  31:     catch (Exception) 
		  32:     { 
		  33:         throw; 
		  34:     } 
		  35:     finally 
		  36:     { 
		  37:         _rw.ReleaseReaderLock(); 
		  38:     } 
		  39: } 
		  40: public static void Writer() 
		  41: { 
		  42:     try 
		  43:     { 
		  44:         _rw.AcquireWriterLock(Timeout.Infinite); 
		  45:         Thread t = Thread.CurrentThread; 
		  46:         int id = _rw.WriterSeqNum; 
		  47:         _writer = id.ToString(); 
		  48:         Console.WriteLine("Thread[{0}]:{1},Write Value is {2}", t.ManagedThreadId, t.ThreadState, _writer); 
		  49:     } 
		  50:     catch (Exception) 
		  51:     { 
		  52:         throw; 
		  53:     } 
		  54:     finally 
		  55:     { 
		  56:         _rw.ReleaseWriterLock(); 
		  57:     } 
		  58: }
		  59:  

 

如果仔細的觀察可以發現Read Value會同時間秀出來,Write Value會慢慢秀出來;讀取器和寫入器是個別佇列,ReaderWriterLock 會在讀取器集合和寫入器集合之間交替,兩者並不會同時執行。

我一直嘗試著要觀察他們之間的交替規則,但一直觀察不出來,看來是交由ReaderWriterLock 自行管理。

image

 

 

 

 

若要手動切到寫入器可利用

UpgradeToWriterLock 方法切換至寫入器鎖定狀態

DowngradeFromWriterLock 方法回到未切入到鎖定狀態

		   1: public static void Reader()
		   2: {
		   3:     try
		   4:     {
		   5:         _rw.AcquireReaderLock(Timeout.Infinite);
		   6:  
		   7:         LockCookie cooke = _rw.UpgradeToWriterLock(Timeout.Infinite);
		   8:  
		   9:         Thread t = Thread.CurrentThread;
		  10:         Console.WriteLine("Thread[{0}]:{1},Read Value is {2}", t.ManagedThreadId, t.ThreadState, _writer);
		  11:         Thread.Sleep(1000);
		  12:  
		  13:         _rw.DowngradeFromWriterLock(ref cooke);
		  14:  
		  15:     }
		  16:     catch (Exception)
		  17:     {
		  18:         throw;
		  19:     }
		  20:     finally
		  21:     {
		  22:         _rw.ReleaseReaderLock();
		  23:     }
		  24: }

image

這樣的功能就像資料庫只能有一個人寫入一樣,是為了維護讀取者資料的一致性。

Thread_ReaderWriterLock.zip

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo