C#多執行緒同步的幾種方法
阿新 • • 發佈:2019-01-25
9.ReaderWriterLockSlim 類
讀寫鎖的概念很簡單,允許多個執行緒同時獲取讀鎖,但同一時間只允許一個執行緒獲得寫鎖,因此也稱作共享-獨佔鎖。在C#中,推薦使用ReaderWriterLockSlim類來完成讀寫鎖的功能。某些場合下,對一個物件的讀取次數遠遠大於修改次數,如果只是簡單的用lock方式加鎖,則會影響讀取的效率。而如果採用讀寫鎖,則多個執行緒可以同時讀取該物件,只有等到物件被寫入鎖佔用的時候,才會阻塞。簡單的說,當某個執行緒進入讀取模式時,此時其他執行緒依然能進入讀取模式,假設此時一個執行緒要進入寫入模式,那麼他不得不被阻塞。直到讀取模式退出為止。同樣的,如果某個執行緒進入了寫入模式,那麼其他執行緒無論是要寫入還是讀取,都是會被阻塞的。
進入寫入/讀取模式有2種方法:
EnterReadLock嘗試進入寫入模式鎖定狀態。
TryEnterReadLock(Int32) 嘗試進入讀取模式鎖定狀態,可以選擇整數超時時間。
EnterWriteLock 嘗試進入寫入模式鎖定狀態。
TryEnterWriteLock(Int32) 嘗試進入寫入模式鎖定狀態,可以選擇超時時間。
退出寫入/讀取模式有2種方法:
ExitReadLock 減少讀取模式的遞迴計數,並在生成的計數為 0(零)時退出讀取模式。
ExitWriteLock 減少寫入模式的遞迴計數,並在生成的計數為 0(零)時退出寫入模式。
程式碼示例如下:
以上為幾種執行緒同步方式,對於同步技術來說,還有很多種其他方式。能力有限,這裡只介紹這幾種。public class Program { static private ReaderWriterLockSlim rwl = new ReaderWriterLockSlim(); static void Main(string[] args) { Thread t_read1 = new Thread(new ThreadStart(ReadSomething)); t_read1.Start(); Console.WriteLine("{0} Create Thread ID {1} , Start ReadSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_read1.GetHashCode()); Thread t_read2 = new Thread(new ThreadStart(ReadSomething)); t_read2.Start(); Console.WriteLine("{0} Create Thread ID {1} , Start ReadSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_read2.GetHashCode()); Thread t_write1 = new Thread(new ThreadStart(WriteSomething)); t_write1.Start(); Console.WriteLine("{0} Create Thread ID {1} , Start WriteSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_write1.GetHashCode()); } static public void ReadSomething() { Console.WriteLine("{0} Thread ID {1} Begin EnterReadLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); rwl.EnterReadLock(); try { Console.WriteLine("{0} Thread ID {1} reading sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); Thread.Sleep(5000);//模擬讀取資訊 Console.WriteLine("{0} Thread ID {1} reading end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); } finally { rwl.ExitReadLock(); Console.WriteLine("{0} Thread ID {1} ExitReadLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); } } static public void WriteSomething() { Console.WriteLine("{0} Thread ID {1} Begin EnterWriteLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); rwl.EnterWriteLock(); try { Console.WriteLine("{0} Thread ID {1} writing sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); Thread.Sleep(10000);//模擬寫入資訊 Console.WriteLine("{0} Thread ID {1} writing end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); } finally { rwl.ExitWriteLock(); Console.WriteLine("{0} Thread ID {1} ExitWriteLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode()); } } }