線程與線程池

1.       線程基礎

Windows中,線程的職責是對CPU進行虛擬化,可將線程理解爲一個邏輯CPU。Windows爲每個進程提供該進程專用的線程。

由於線程是對CPU進行虛擬化,使得線程會產生空間(內存耗用)和時間(上下文切換)上的開銷。

  1.        空間開銷:在默認情況下,Windows爲每個線程的用戶模式棧分配1MB內存。

  2.        時間開銷:在任何給定的時刻,Windows只將一個線程分配給一個CPU。該線程允許運行一個“時間片”。一旦時間片到期,Windows就上下文切換到另一個線程。Windows執行一次上下文切換大約需要30毫秒。

結論:儘可能避免使用線程,但有時必須使用線程來提高程序的響應速度和執行多任務。

2.       前後臺線程

在CLR中的線程只有前臺線程和後臺線程兩種。一個進程中所有前臺線程都停止運行時,CLR將強制終止所有正在運行的後臺線程,並且不會拋出異常。只要有一個前臺線程在運行,應用程序的進程就在運行。所以前臺線程適合執行關鍵任務,後臺現在適合執行非關鍵任務。下面代碼用於說明前後臺線程與進程的關係。

 private static void Main(string[] args)
        {
            //創建專用線程
            var t = new Thread(ThreadWork)
                {
                    Name = "NewThread1",
                    //指定是否爲後臺線程,修改該屬性驗證前後臺線程與進程的關係
                    IsBackground = false
                };
            //創建專用線程
            
            t.Start();
            Console.WriteLine("進程結束");
            
        }

        private static void ThreadWork()
        {
            Console.WriteLine("線程啓動:" + Thread.CurrentThread.Name);
            //讓當前線程休眠3秒鐘,把線程執行權讓給優先級高的其他線程執行,
            //避免一直佔有線程執行權。3秒鐘過後線程醒來,一定能立即恢復執行。
            //這是因爲在那個時刻,其它線程可能正在運行而且沒有被調度爲放棄執行,除非
            //1、“醒來”的線程具有更高的優先級
            //2、正在運行的線程因爲其它原因而阻塞。
            Thread.Sleep(3000);
            Console.WriteLine("線程完成" + Thread.CurrentThread.Name);
             
            //這個方法返回後,該專用線程將終止。
           
        }

 

3.       線程池

3.1.    線程池基礎

由第一節線程基礎的結論可知,我們應該在保持代碼響應能力的同時創建儘可能少的線程。CLR線程使用Windows的線程處理能力,一個CLR線程直接對應一個Windows線程。爲了改善創建和銷燬線程帶來的空間和時間上的開銷,CLR包含代碼來管理它自己的線程池。可將線程池想象爲可由你的應用程序使用的一個線程集合。每個CLR一個線程池。

CLR初始化時,線程池中沒有線程。在內部,線程池維護一個操作請求隊列。應用程序向線程池發出一個請求時,如果線程池中沒有線程,就創建一個新線程用於處理應用程序的請求。當線程池中的線程完成任務後,線程不會被銷燬,而是返回到線程池中,並且進入空閒狀態,等待響應另一個請求。由於線程池中的線程處理完任務後不銷燬自身,所以不再產生額外的性能損失。如果應用程序停止向線程池發出請求,線程池中的線程都處於空閒狀態,一段時間後,線程會自己醒來終止自己並且釋放資源。線程終止自己時會產生一定的性能損失,然而,線程池中的線程終止自己是因爲閒得慌,說明應用程序本身沒做什麼事,所以這個性能損失關係不大。

3.2.    線程池管理

不同CLR的版本,其內部結構有一定的變化。最好將線程池看成黑盒子。目前,線程池的工作非常理想,強烈建議信任它。

  1.        設置線程池上限

CLR允許開發人員設置線程池的最大線程數,但永遠都不應該爲線程池設置上限,因爲可能發生飢餓或死鎖。由於存在飢餓和死鎖問題,所以CLR團隊一直都在穩步增加線程池默認能夠擁有的最大線程數,目前默認值爲1000個線程。

 

注:參考CLR via C#第三版 第25、26章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章