C# 線程同步與線程池
樣本很簡單,準備5個線程,每個線程同時向控制台輸出數字,然後觀察輸出結果。
代碼說明:
////線程列表
private static List<Thread> _threadList; static voidMain(string[] args) { Program._threadList= new List<Thread>(); ////附加5個線程 for (inti = 0; i < 5; i++) { Program.AppendThread(); } ////開始執行所有測試線程 Program.ExecuteThread(); ////按任意鍵退出 Console.ReadLine(); } /// <summary> /// 將新的測試線程附加到測試線程列表,線程執行邏輯就是輸出10個數字/// 注意初始化的時候設定為後台線程了,這樣可以保證主線程退出的時候其他線/// 程自動結束 /// </summary> public staticvoid AppendThread() { Program._threadList.Add(newThread(new ThreadStart( () => { for (int i = 0; i < 10; i++) { Console.WriteLine(i); } })){ IsBackground = true }); } /// <summary> /// 開始執行所有測試線程 /// </summary> public staticvoid ExecuteThread() { foreach(Thread t in _threadList) { t.Start(); } }
觀察執行結果,我們可以看到結果如下:
根據結果(數位輸出是不規律的)可知,線程之間發生了幹擾。策略就是,加一個同步成員來進行線程同步:
/// <summary> /// 多線程同步的對象 /// </summary> private static object _syncObj = new object();另外,線上程執行的地方加鎖:Program._threadList.Add(newThread(new ThreadStart( () => { lock (_syncObj) { for (int i = 0; i < 10;i++) { Console.WriteLine(i); } } })) { IsBackground = true });
觀察結果:
可以看到通過Lock關鍵字,對一個多線程同步的變數加鎖的確可以使得線程同步。
現在看一下第二種方式:
使用monitor關鍵字進行同步,代碼:
Monitor.Enter(_syncObj); try { for (int i = 0; i < 10; i++) { Console.WriteLine(i); } } finally { Monitor.Exit(_syncObj); }
查看結果,會發現線程已經同步了。
第三種方式:
現在讓我們重構一下代碼,建立一個ThreadManager的類,把類的職責都搬進去:
class ThreadManager { /// <summary> /// 線程列表 /// </summary> private staticList<Thread> _threadList; staticThreadManager() { _threadList = new List<Thread>(); } /// <summary> /// 附加新線程 /// </summary> public staticvoid AppendThread() { ThreadManager._threadList.Add(newThread(new ThreadStart( () => { for (int i = 0; i < 10; i++) { Console.WriteLine(i); } })){ IsBackground = true }); } /// <summary> /// 開始執行所有線程 /// </summary> public staticvoid ExecuteThread() { foreach(Thread t in _threadList) { t.Start(); } } }
Main函數調用的代碼做相應的改變:
static voidMain(string[] args) { ////附加5個線程 for (int i = 0; i < 5; i++) { ThreadManager.AppendThread(); } ////開始測試 ThreadManager.ExecuteThread(); ////按任意鍵繼續 Console.ReadLine(); }
由於沒有對線程同步做任何處理,結果肯定可以猜到,線程是不同步的:
現在對ThreadManager這個類加上特性:[Synchronization],再次運行之,發現線程同步了,這就是線程同步的第四種方案,用起來很簡單,但是首先它要求執行邏輯都放在一個類中,由於它可以確保這個類中的所有方法都是安全執行緒的,因此它的效能相對低效。
線程同步還有方法嗎?答案是肯定的,那就是第四種方法—線程池。
現在來看一下如何用線程池來實現:
static void Main(string[]args) {/////定義一個waitCallback對象,並定義它的行為,就是向控制台輸出十個數字同時可以傳遞/////一個參數(這個參數是可選的) WaitCallback work = new WaitCallback((o)=> { for(int i = 0; i < 10; i++) { Console.WriteLine(i); } }); ////執行5次 for (inti = 0; i < 5; i++) {/////如果這裡需要傳遞參數,可以調用另一個重載方法 ThreadPool.QueueUserWorkItem(work); } ////按任意鍵繼續 Console.ReadLine(); }
這樣就完成了剛剛的邏輯嗎?是的,運行之後我們可以看到結果,線程是同步的。
多線程還帶來了哪些好處?
線程池減少了線程建立、開始和停止的次數,從而提高了效率;
使用線程池,能夠使我們將注意力放到商務邏輯上而不是多線程架構上(然而在某些情況應優先使用手工線程管理)
如果需要前台線程或者設定優先權別,或者線程池中的線程總是後台線程,且他的優先順序是預設的;
如果需要一個帶有固定標識的線程便於退出,掛起或通過名字發現它。
以上就是C# 線程同步與線程池 淺析的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!