由CLR via C#(第三版) ,摘抄記錄...算法
一、線程是CPU的虛擬化,windows爲每一個進程提供專用線程(CPU)
二、線程開銷:內存和時間。
線程內核對象—OS爲系統中建立的每一個線程都分配並初始化這種數據結構之一。其中包含對線程進行描述的屬性,和上下文。上下文是內存塊,x86的是約700字節,x64是約1240,ia64是2500。
線程環境塊TEB,用戶模式中的內存塊(應用程序代碼能快速訪問的空間),一個TEB一個內存頁,x86和x64都是4KB,IA64是8KB。 TEB包含線程的異常處理鏈首(head)。進入每個try都在後面插入一個節點,退出try時刪除該節點。 TEB還包含線程的本地存儲 數據,以及GDI和OpenGL圖形使用的數據。
用戶模式棧 存儲傳遞給方法的局部變量和實參,還包含一個地址,指出方法返回時,線程從何處執行。默認1MB。
內核模式棧 32位windows下爲12KB,64的是24KB。
DLL線程鏈接和線程分離通知 windows策略決定。。C#和其餘託管語言的DLL沒有DLLMain函數,不收通知,這提高性能。windows
三、windows只將一個線程分配給一個CPU,容許其運行一個 時間片 ,上下文切換。
切換:將cpu寄存器的值保存內核對象內部的上下文結構中,選出一個新線程供調度,將其內的上下文結構值加載到CPU。
大約每30毫秒執行一次切換。淨開銷。並且還會切換高速緩存cache。儘量避免切換。
時間片結束時,若是windows決定再調度同一線程,就沒有切換。這顯著改進性能。
四、垃圾回收時,CLR暫停全部線程,遍歷他們的棧進行標記,再遍歷棧,再恢復全部線程。因此,減小線程數量會顯著提高垃圾回收器的性能。調試時也掛起,線程越多,調試體驗越差。
單個線程不會在多個內核CPU上調度,應在確保響應能力的同時建立儘可能少的線程。理性使用線程。緩存
五、超線程CPU,芯片中包含2組架構狀態,只有一組在執行,對於windows,看起來像是2個CPU,全部windows會同時調度2個線程。芯片一次只能執行一個。數據結構
六、NUMA架構機器,(略)架構
七、CLR線程和windows線程: CLR使用的是windows的線程處理能力。一個CLR線程直接對應一個windows線程。併發
八、使用專用線程執行異步的計算限制操做。異步
建議避免採用,應儘可能使用CLR的線程池來執行異步計算限制操做。ide
顯示建立本身線程的條件:函數
優先級高,不建議更改線程池的優先級;性能
表現爲一個前臺線程,防止應用程序在線程結束它的任務以前終止。線程池中的是後臺線程。
一個計算限制的任務須要長時間運行。
要調用Abort方法提早終止它。
Thread.Join()等待線程終結。
九、使用線程的理由 代碼隔離健壯性,簡化編碼,併發。
觀點改變,CPU計算能力富餘,應大膽消費。
十、線程調度和優先級
搶佔式操做系統,使用算法判斷在什麼時間調度哪些線程多少時間。
一個時間片後,windows檢查現有全部線程內核對象,有資源的適合調度。從spy++能夠查看切換的次數。線程在任什麼時候間能夠被搶佔,windows調度另外一個。你不能阻止其餘線程的運行。
因此,windows是搶佔式操做系統,不是實時操做系統,CLR使託管代碼的行爲更不實時。好比:DLL的JIT加載,代碼的JIT編譯,GC沒法預測的介入。
線程優先級從0(最低)-31(最高),系統啓動時有個爲0的零頁線程的特殊線程,惟一一個0的線程,在沒有其餘進程要調度時,將系統RAM全部空閒頁清零。
優先級類(priority class) :Idle,Below Normal,Normal,Above Normal,High和Realtime。 優先級類是用於進程的。每一個線程的優先級取決於 他所屬的進程的優先級類和在該進程內他自身的優先級——倆者合成基礎優先級——動態優先級是OS確保線程可響應,不一直飢餓所產生。可是16-31之間的線程,系統不提高他們的優先級。0-15的才提高。
應用開發人員永遠不直接處理優先級。Normal的Normal是8,大多數程序都是8的優先級。Windwos永遠不會調度進程,只調度線程。進程根據啓動它的進程來分配一個優先級。大多數進程都是windows資源管理器啓動的,屬於Normal。
託管應用程序不該該表現爲擁有本身的進程;相反,他們應該表現爲在一個AppDomain中運行。 能夠更改他的線程相對優先級,設置Thread的Priority屬性。System.Diagnostics命名空間包含一個Process類和ProcessThread類,提供進程和線程的windows視圖。AppDomain和Thread類,公開了應用域和線程的CLR視圖。
十一、 前臺線程和後臺線程
線程在CLR中要麼是前臺,要麼是後臺。一個進程中的全部前臺中止時,CLR強制終止扔在運行的任何後臺線程。--直接終止,不拋出異常。
1 public static void Main() 2 { 3 // 建立一個新線程(默認爲前臺線程) 4 Thread t = new Thread(Worker); 5 6 Console.WriteLine(t.IsBackground.ToString()); 7 // 使線程成爲一個後臺線程 8 t.IsBackground = true; 9 t.Start(); // 啓動線程 10 // 若是 t 是一個前臺線程,則應用程序大約 10 秒後才終止 11 // 若是 t 是一個後臺線程,則應用程序當即終止 12 Console.WriteLine("Returning from Main"); 13 Console.Read(); 14 15 } 16 private static void Worker() 17 { 18 Thread.Sleep(10000); // 模擬作 10 秒鐘的工做 19 // 下面這一行代碼,只有在由一個前臺線程執行時,纔會顯示出來 20 Console.WriteLine("Returning from Worker"); 21 22 Console.Read(); 23 } 24 }
在線程生存期內,隨時可先後變換。應用的主線程以及經過Thread對象顯示建立的都默認前臺,線程池默認後臺。由進入托管執行環境的本地代碼建立的線程被標記爲後臺。應儘可能避免使用前臺線程。
wintellect類庫,做者寫的....
~~~~~~~~~~待續~~