目錄:算法
26.1 Windows爲何要支持線程緩存
26.2 線程開銷服務器
26.3 中止瘋狂數據結構
26.4 CPU發展趨勢架構
26.5 CLR線程和Windows線程併發
26.6 使用專用線程執行異步的計算限制操做異步
26.7 使用線程的理由函數
26.8 線程調度和優先級性能
26.9 前臺線程和後臺線程學習
26.10 繼續學習
做爲一個Windows概念,線程的職責是對CPU進行虛擬化。Windows爲每一個進程都提供了改進程專用的線程(功能至關於一個CPU)。應用程序的代碼進入死循環,與那個代碼關聯的進程回「凍結」,但其餘進程不會凍結,會繼續執行。
線程容許用戶強制終止彷佛已凍結的應用程序。和一切虛擬化機制同樣,線程有空間(內存耗用)和時間(運行時的執行性能)上的開銷。
線程內核對象:OS爲系統中建立的每一個線程都分配並初始化這種數據結構之一。數據結構包含一組對線程進行描述的屬性。數據結構還包含所謂的線程上下文。上下文是包含CPU寄存器集合的內存塊。
線程環境塊(TEB):TEB是在用戶模式(應用程序代碼能快速訪問的地址空間)中分配和初始化的內存塊。TEB耗用1個內存頁。TEB包含線程的異常處理鏈首。線程進入的每一個try塊都在鏈首插入一個節點;線程退出try塊時從鏈中刪除改節點。TEB還包含線程的「線程本地存儲」數據,以及由GDI和OpenGL圖形使用的一些數據結構。
用戶模式棧:用戶模式棧存儲傳給方法的局部變量和實參。它包含一個地址;指出當前方法返回時,線程應該從什麼地方接着執行。
內核模式棧:應用程序代碼向操做系統中的內核模式函數傳遞實參時,還會使用內核模式棧。
DLL線程鏈接(attach)和線程分離(detach)通知:Windwos的一個策略是,任什麼時候候在進程中建立線程,都會第哦啊用進程中加載的全部非託管DLL的DllMain方法,並向該方法傳遞DLL_THREAD_ATTACH標誌。任何線程終止,都會調用進程中的全部非託管DLL的DllMain方方法,並向方法傳遞DLL_THREAD_DETACH標誌。
Windows任什麼時候刻只將一個線程分配給一個CPU。那個線程能運行一個「時間片(也稱爲「量」或「量程」)」的長度。時間片到期,Windows就上下文切換到另外一個線程:
1.將CPU寄存器的值保存到當前正在運行的線程的內核對象內部的一個上下文結構中。
2.從現有線程集合中選出一個線程供調度。若是該線程由另外一個進程擁有,Windows在開始執行任何代碼或者接觸任何數據以前,還必須切換CPU「看見」的虛擬地址空間。
3.將所選上下文結構中的值加載到CPU的寄存器中。
上下文切換時淨開銷;所產生的開銷不會換來任何內存或性能上的收益。因此說上下文切換時經過犧牲性能來換取更好的用戶體驗。
執行上下文切換所需的時間取決於CPU架構和速度。而填充CPU緩存所須要的時間取決於系統中運行的應用程序,CPU緩存的大小以及其餘各類因素。
執行垃圾回收時,CLR必須掛起(暫停)全部線程,遍歷它們的棧來查找根以便對堆中的對象進行標記,再次遍歷它們的棧,在恢復全部線程。
多個CPU
超線程芯片
多核芯片
CLR使用Windows的線程處理功能,CLR線程徹底等價於Windows線程。
知足如下條件就能夠建立本身的線程:
線程須要以非普通線程優先級運行。
須要線程表現爲要給前臺線程,防止應用程序在線程結束任務前終止。
計算限制的任務須要長時間運行。
要啓動線程,並可能調用Thread的Abort方法來提早終止它。
可響應性(一般是對於客戶端GUI應用程序)
Windows爲每一個進程提供它本身的線程,確保發生死循環的應用程序不會妨礙其餘應用程序。
性能(對於客戶端和服務器應用程序)
因爲Windows每一個CPU調度一個線程,並且多個CPU能併發執行這些線程,因此同時執行多個操做能提高性能。
搶佔式操做系統必須使用算法判斷在何時調度哪些線程多長時間——線程可在任什麼時候間中止(被搶佔)並調度另外一個線程。(每一個線程的內核對象包含一個上下文結構,上下文結構反映了線程上一次執行完畢後CPU寄存器的狀態。在一個時間片以後,Windows檢查現存的全部線程內核對象。在這些對象中,只有那些沒有正在等待什麼的線程才適合調度。Windows選擇一個可調度的線程內核對象,並上下文切換到它。Windows實際記錄了每一個線程被上下文切換到的次數。而後,線程開始執行代碼,並在其進程的地址空間處理數據。又過過了一個時間片以後,Windows執行下一次上下文切換。Windows從系統啓動開始便一直執行上下文切換,直到系統關閉爲止。)
每一個線程都分配了從0到31的優先級。飢餓:較高優先級的線程佔用了太多CPU時間,形成較低優先級的線程沒法運行。
系統啓動時會建立一個特殊的零頁線程,該線程的優先級是0,並且是整個系統惟一優先級爲0的線程。在沒有其餘線程須要「幹活兒」的時候,零頁線程將系統RAM的全部空閒頁清零。
進程優先級類:Idle,Below Normal,Above Normal,High,Realtime.
相對線程優先級:Idle,Lowest,Below Normal,Normal,Above Normal,Highest,Time-Critical.
相對線程優先級 | 進程優先級類 | |||||
Idle | Below Normal | Normal | Above Nomal | High | Realtime | |
Time-Critical | 15 | 15 | 15 | 15 | 15 | 31 |
Highest | 6 | 8 | 10 | 12 | 15 | 26 |
Above Normal | 5 | 7 | 9 | 11 | 14 | 25 |
Normal | 4 | 6 | 8 | 10 | 13 | 24 |
Below Normal | 3 | 5 | 7 | 9 | 12 | 23 |
Lowest | 2 | 4 | 3 | 8 | 11 | 22 |
Idle | 1 | 1 | 1 | 1 | 1 | 16 |
CLR將每一個線程要麼視爲前臺線程,要麼視爲後臺線程。一個進程的全部前臺線程中止運行時,CLR強制終止仍在運行的任何後臺線程。這些後臺線程被直接終止,不拋出異常。
應用程序的主線程以及經過構造一個Thread對象來顯式建立的任何線程都默認爲前臺線程,線程池線程默認爲後臺線程。由進入托管執行環境的本機代碼建立的任何線程被標記爲後臺線程